давайте возьмем следующий код:
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);
}
Обе следующие строки:
pass_by_copie(test::USER);
pass_by_const_ref(test::USER);
выдать следующую ошибку под g++ 4.7
:
неопределенная ссылка на `test :: USER ‘
Я осознаю тот факт, что нет test::USER
, (строка закомментирована специально)
У меня есть два вопроса:
Почему явный случай test::USER
необходимо, пока нет явного экземпляра test::NATIVE
необходим для вызова функции pass_by_copie
?
Почему я могу позвонить pass_by_rvalue_ref
по простоте создания временной копии из test::USER
в то время как компилятор не может (или не хочет) неявно создавать тот же самый экземпляр при вызове pass_by_copie
с test::USER
?
Спасибо
Clang 4.1 дает мне эту ошибку:
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)
Я предполагаю, что здесь происходит test::NATIVE
может быть просто заменено значением 4.2
где он используется, и на самом деле не требует символа. Но test::USER
будучи экземпляром класса, а не скаляра, требует символа, чтобы все ссылки на test::USER
ссылаются на тот же объект. Учитывая это, вам действительно нужен явный экземпляр.
Из раздела 3.2 C ++ 11:
Переменная, имя которой появляется в качестве потенциально оцениваемого выражения: УСО используемый если это не объект, который удовлетворяет требованиям для появления в константном выражении, и преобразование lvalue-в-значение сразу применяется.
а также
Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе
Таким образом, определение требуется, потому что test::USER
используется odr, и, очевидно, он используется odr, потому что он не подвергается немедленному преобразованию lvalue в rvalue. Это удивляет меня, призыв к pass_by_copie
похоже, что он выполняет преобразование lvalue в rvalue.