jeudi 2 novembre 2017

Safe to pass empty variables by value, even with no linkage?

If I pass an empty variable by value, even though it has no linkage, 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 linkage, 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 linkage?

Aucun commentaire:

Enregistrer un commentaire