constexpr:文字类型复制行为

时间:2012-12-07 15:36:34

标签: c++ c++11 static-members constexpr

让我们采用以下代码:

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的实例。 (这条线是故意评论的)


我有两个问题:

  1. 为什么需要test::USER的显式实例,而调用函数test::NATIVE时不需要pass_by_copie的显式实例?

  2. 为什么我可以通过明确地从pass_by_rvalue_ref创建临时copie来调用test::USER,而编译器在调用{{{}时无法(或不希望)自己隐式创建相同的copie 1}}与pass_by_copie

  3. 谢谢

2 个答案:

答案 0 :(得分:2)

从C ++ 11的3.2节开始:

  

名称显示为可能已评估的表达式的变量是 odr-used ,除非它是满足出现在常量表达式中的要求的对象,并且lvalue-to-rvalue转换是立即的应用

  

每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义

因此定义是必需的,因为test::USER使用的是odr,并且显然它使用的是odr,因为它不会立即进行左值到右值的转换。令我感到惊讶的是,对pass_by_copie的调用看起来像是执行左值到右值的转换。

答案 1 :(得分:1)

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的所有引用都引用同一个对象。鉴于此,您实际上确实需要显式实例。