If I pass an empty variable by value, even though it has no definition, is it safe and compliant?
I came across this issue while working on code, overloading |
, to make this print the contents of the vector v
:
v | print; // prints the vector v
The code I present here works for me with g++
and clang
, even though print
is an extern
variable with no linkage, but I wonder if I'm pushing the standard too far. This is for c++11/c++14, I guess this is solved in c++17 with inline
variables?
First, my initial code. The goal is to allow things like v|print
to print a vector. I have bigger goals too, related to ranges, but I'll focus on this tiny example here
struct print_tag_t {};
print_tag_t print;
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
int main() {
std::vector<int> v{2,3,5,7};
v | print;
}
Moving this to a header
If I move this into a header, I can make the operator|
overload as inline
. But what about print
? I have found that I can make it extern
to avoid the linker error about duplicate symbols
// print.hh
struct print_tag_t {};
extern // extern, as I can't use inline on a variable
print_tag_t print;
inline
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
This works for me. Somehow, even though print
has no definition, I can do v|print
. I guess it's because it's empty and therefore there is no value to inspect and therefore it never needs an address.
Are compilers required to allow my v|print
example to work? Where, to clarify, print
is extern
and hasn't been given any definition?
const struct print_tag_t {} print;
in your header file? No problem with multiple definitions. ` – Cloeprint
declaration in an anonymous namespace, so it is local to each translation unit, or declare it new-ageinline
or old-schoolstatic
. – Nathansonenum actions { print };
and then overload forenum actions
and you do not have to worry about the linkage issue – Ritualism