[英]Understanding static constexpr member variables
我对C ++ 11中的static constexpr
成员变量有一些疑惑。
template<typename T>
struct cond_I
{ static constexpr T value = 0; };
// specialization
template<typename T>
struct cond_I< std::complex<T> >
{ static constexpr std::complex<T> value = {0,1}; };
cout << cond_I<double>::value << endl; // this works fine
cout << cond_I< complex<double> >::value << endl; // linker error
但是,如果我first.hpp
添加到first.hpp
一切正常。
template<typename T1>
constexpr std::complex<T1> cond_I< std::complex<T1> >::value;
我理解(我可能是错的)是, cond_I< std::complex<double> >::value
需要一个定义,但在前一种情况下它只有声明。 但那么cond_I<double>::value
怎么样? 为什么它不需要定义?
再次,在另一个头文件second.hpp
,我有:
// empty struct
template<typename T>
struct eps
{ };
// special cases
template<>
struct eps<double>
{
static constexpr double value = 1.0e-12;
};
template<>
struct eps<float>
{
static constexpr float value = 1.0e-6;
};
在这种情况下,以下代码完美地工作,没有任何eps<>::value
定义。
cout << eps<double>::value << endl; // works fine
cout << eps<float>::value << endl; // works fine
在这些场景中,有人可以解释一下static constexpr
成员变量的不同行为吗?
对于gcc-5.2
和clang-3.6
这些行为也是相同的。
根据标准9.4.2 / p3静态数据成员[class.static.data] ( Emphasis Mine ):
如果非易失性const静态数据成员是整数或枚举类型,则它在类定义中的声明可以指定一个大括号或大小为初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式(5.20) )。 可以使用
constexpr
说明符在类定义中声明文字类型的静态数据成员; 如果是这样,它的声明应指定一个大括号或等于初始化器,其中作为赋值表达式的每个initializer子句都是一个常量表达式。 [注意:在这两种情况下,成员可能会出现在常量表达式中。 - 结束注释]如果程序中使用了odr-used(3.2),并且命名空间作用域定义不包含初始化程序,则仍应在名称空间作用域中定义该成员。
正如MM早先在评论中解释的那样, ostream::operator<<(ostream&, const complex<T>&)
通过引用传递,因此在程序中将值视为odr-used。 因此,正如上面的措辞所规定的那样,你必须提供一个定义。
现在你已经发现基本类型是按值传递的,这就是为什么不需要定义的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.