【发布时间】:2015-03-06 00:21:29
【问题描述】:
这个问题是关于带有标志 /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,那么编译器会简单地优化这些常量。
【问题讨论】:
-
“如果使用 b_ 显然应该如此。使用此处的引用不会改变任何事情。为什么这会相关?
-
也许我回答的最后一段对您的真正问题至关重要?如果是这样,显然您总是需要将静态成员初始化分离到一个单独的翻译单元中。
-
@sehe:这是相关的,因为我无法在 Visual Studio C++13 中使用 /Za 编译 boost::pool。我将罪魁祸首追溯到问题中的行为。查明责任人后,我会向 boost 人员或 MS 人员报告此错误。
-
我发布了一个几乎详尽的{max,ternary}/{enum,static-field-in-class,static-field-out-of-class} in the comment at my answer 比较。 TL; DR 我是对的:没关系。编译器内联
std::max变体只是一样(应该) -
@sehe:谢谢。您所做的证明该页面中的编译器没有显示错误。但是,这些编译没有问题: #include
struct A { static const int a = 5; A(){ std::cout
标签: templates c++11 boost initialization static-members