Reputation: 13288
let's take the following code:
class const_int
{
public:
constexpr const_int(int data) : data_(data) {}
constexpr const_int(const const_int &) = default;
constexpr const_int(const_int &&) = default;
private:
int data_;
};
class test
{
public:
constexpr static const const_int USER = 42;
constexpr static const double NATIVE = 4.2;
};
// constexpr const const_int test::USER;
void pass_by_copie(double)
{
}
void pass_by_copie(const_int)
{
}
void pass_by_const_ref(const const_int&)
{
}
void pass_by_rvalue_ref(const_int&&)
{
}
int main(void)
{
pass_by_copie(test::NATIVE);
pass_by_copie(test::USER);
pass_by_const_ref(test::USER);
pass_by_rvalue_ref(const_int(test::USER));
return (0);
}
Both of the following lines :
pass_by_copie(test::USER);
pass_by_const_ref(test::USER);
produce the following error under g++ 4.7
:
undefined reference to `test::USER'
I am aware of the fact that there is no instance of test::USER
. (the line is commented on purpose)
I have two questions :
Why is an explicit instance of test::USER
needed while no explicit instance of test::NATIVE
is needed to call the function pass_by_copie
?
Why can i call pass_by_rvalue_ref
by explicity creating a temporary copie from test::USER
while the compiler is unable (or doesn't want) to create the same copie implicitly himself when calling pass_by_copie
with test::USER
?
Thank you
Upvotes: 3
Views: 353
Reputation: 283803
From section 3.2 of C++11:
A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied.
and
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program
So the definition is required because test::USER
is odr-used, and apparently it is odr-used because it does not immediately undergo lvalue-to-rvalue conversion. That surprises me, the call to pass_by_copie
looks like it performs an lvalue-to-rvalue conversion.
Upvotes: 2
Reputation: 185821
Clang 4.1 gives me this error:
Undefined symbols for architecture x86_64:
"test::USER", referenced from:
_main in Untitled-gXrry2.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I'm assuming what's going on here is test::NATIVE
can be simply replaced with the value 4.2
where it's used, and doesn't actually require a symbol. But test::USER
, being an instance of a class rather than a scalar, does require a symbol so that all references to test::USER
refer to the same object. Given this, you actually do need the explicit instance.
Upvotes: 1