问题
The definition in the standard for odr-used is pretty confusing when you get into the details (at least, for me it is). I generally rely on the informal definition of "If a reference is taken", except when an lvalue-to-rvalue conversion is available. For integral constants, they should be treated as rvalues, which seems like it should be excluded from the reference rule. Here is my sample code that is failing to link:
class Test
{
public:
Test();
static constexpr int MIN_VALUE { 5 };
int m_otherValue = 10;
};
Test::Test()
{
m_otherValue = std::max(m_otherValue, MIN_VALUE);
}
int main()
{
Test t;
}
And the linker error that I get:
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out /tmp/main-e2122e.o: In function `Test::Test()': main.cpp:(.text+0x2): undefined reference to `Test::MIN_VALUE' clang: error: linker command failed with exit code 1 (use -v to see invocation)
Live sample: http://coliru.stacked-crooked.com/a/4d4c27d6b7683fe8
Why is the definition of MIN_VALUE
required? It's just a constant to a literal value, the compiler should optimize this out as std::max(m_otherValue, 5)
. So I just don't get it.
回答1:
std::max takes its arguments by reference, not by value. Performing the lvalue-to-rvalue conversion and then constructing a temporary object from that rvalue is not allowed. std::max
could be checking that the two arguments are references to the same object, for all the compiler knows, and that check would be required to evaluate as true
if called as std::max(MIN_VALUE, MIN_VALUE)
.
回答2:
If you read a reference for std::max you will see that it takes it arguments by reference, and according to this odr-used reference
Informally, an object is odr-used if ... a reference is bound to it ...
Since you pass MIN_VALUE
to a function which takes a reference, the member is odr-used and needs a separate definition.
来源:https://stackoverflow.com/questions/31485656/linker-error-with-static-constant-that-doesnt-seem-to-be-odr-used