这个问题是关于带有标志/Za 的 Visual Studio C++ 2013 中模板和静态整数常量之间的关系。它对 boost 库有影响。
首先,让我们检查没有模板的代码:
struct easy
{
static const int a = 5;
const int b;
easy( int b_ ) : b( std::max( b_, a ) )
{}
};
const int easy::a;
int main()
{
easy d_Easy( 0 );
return 0;
}
根据compiler option /Za的手册页| :“在标准(/Za)下,您必须对数据成员进行类外定义”。该页面中的示例和上面的代码在类中声明了静态常量并在那里指定了它的值。 this link 中解释了对类外定义的需要。 .
现在,让我们看看模板的问题。
template< class T >
struct problem
{
static const int a = 5;
const int b;
problem( int b_ ) : b( std::max( b_, a ) )
{}
};
template< class T >
const int problem< T >::a;
int main()
{
problem< char > d_Bad( 666 );
return 0;
}
使用/Za 编译时,链接器会抛出错误“LNK2019:未解析的外部符号”。选项/Ze 不会出现该错误。主要问题是某些 boost 库在类似于上述代码段的代码中使用 BOOST_STATIC_CONSTANT 和 BOOST_NO_INCLASS_MEMBER_INITIALIZATION。
破解一些:
template< class T >
struct fixed
{
static const int a;
const int b;
fixed( int b_ ) : b( std::max( b_, a ) )
{}
};
template< class T >
const int fixed< T >::a = 5;
int main()
{
fixed< char > d_Good( 777 );
return 0;
}
此代码现在使用/Za 编译。
问题:
1) C++11 标准对模板和静态整数常量有什么看法?他们可以/必须有一个类外定义,但它们的值在类定义中提供吗?
2)boost有一些解决方法吗?
更新
重要的是保留
std::max
在代码中,因为(我认为)它试图获取对其参数的引用。如果有人使用 b_<a
然后编译器简单地优化这些常量。
最佳答案
首先,类中静态数据成员的声明绝不是定义。 如果您使用该变量,则必须存在定义 - 当然是下课了。std::max
确实 odr 使用 a
, 因为它的参数是引用,并且如果引用绑定(bind)到变量([basic.def.odr]/3),则变量是 odr-used。 (这确实是 max
的一个问题 - 它不应该直接使用 a
,真的。)
在@sehe 的回答中,他直接使用三元运算符,避免使用 odr,因为立即应用左值到右值的转换并产生一个常量表达式。
Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist; in particular, the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
并且定义完全按照您所做的那样完成。 [temp.static]/1:
A definition for a static data member or static data member template may be provided in a namespace scope enclosing the definition of the static member’s class template.
[ Example:
template<class T> class X { static T s; }; template<class T> T X<T>::s = 0;
当成员为
const
时,可以在类内声明中提供初始化程序整数类型,但这不会影响 ODR 在这方面的语义。仍然需要以相同的方式定义定义,并按照您所做的那样编写。 因此,您所看到的似乎只是一个 VC++ 错误。
关于templates - C++模板静态整数常量: out of class definition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27830761/