Reputation: 781
Consider the following code:
class Test {
public:
static const int VALUE = 100;
};
std::tuple<int> foo(std::tuple<int> value) {
return value;
}
int main()
{
auto t = std::make_tuple(Test::VALUE); // This compiles fine
auto t1 = foo(std::make_tuple(Test::VALUE)); // undefined reference to `Test::VALUE' linker error
}
According to the other question (What does it mean to "ODR-use" something?) and the answer:
In plain word, odr-used means something(variable or function) is used in a context where the definition of it must be present.
In the first case (variable t
) the variable VALUE
is not odr-used because only it' value is needed. But in the second case why the code won't compile? If I would pass t
instead of passed rvalue(?) the code would compile fine. How the second case differs from the first and why VALUE
is odr-used here?
Upvotes: 3
Views: 405
Reputation: 40836
make_tuple
takes the argument by const int&
(since it's a constant lvalue and it takes a T&&
argument), and binding a reference to a value is an ODR-use.
Both cases are ill-formed no diagnostic required. At high optimisation levels of gcc for example, the entire program is optimised out and there are no linker errors, where at no optimisation, both statements give linker errors.
To make it not an ODR use, you can convert it to an rvalue:
// Various ways to force the lvalue-to-rvalue conversion
auto t = std::make_tuple(int(Test::VALUE));
auto t1 = foo(std::make_tuple((void(), Test::VALUE)));
auto t2 = foo(std::make_tuple(+Test::VALUE));
(So std::make_tuple
takes an int&&
of a temporary)
Or you can make the definition inline
(Easiest with constexpr
):
class Test {
public:
static constexpr int VALUE = 100;
};
Upvotes: 3
Reputation: 141165
In the first case (variable t) the variable VALUE is not odr-used because only it' value is needed.
No. It's value is needed and it is ODR used.
But in the second case why the code won't compile?
Because the compiler you are using is not smart enough to optimize the second snippet of code. For example, both lines compile fine on gcc9.3 with -O1.
Upvotes: 2