C++ 从C+中删除constexpr+;14模板专业化?
基本问题是,是否可以从专用模板方法中添加或删除constexpr 让我们假设以下代码:C++ 从C+中删除constexpr+;14模板专业化?,c++,gcc,clang,template-specialization,constexpr,C++,Gcc,Clang,Template Specialization,Constexpr,基本问题是,是否可以从专用模板方法中添加或删除constexpr 让我们假设以下代码: //this is my general vector template with a constexpr default ctor template<typename T, typename STORE> struct alignas(16) vec { union { STORE st; struct { T x; T y; T z; T w; };
//this is my general vector template with a constexpr default ctor
template<typename T, typename STORE>
struct alignas(16) vec {
union {
STORE st;
struct { T x; T y; T z; T w; };
};
inline explicit constexpr vec() noexcept :
x{0}, y{0}, z{0}, w{0} {
}
};
//and this is the SSE enabled version, where we cannot use
//constexpr because of _mm_setzero_ps, so let's remove it...
template<>
inline vec<float, __m128>::vec() noexcept :
st(_mm_setzero_ps()) {
}
//这是我的常规向量模板,带有一个constexpr默认构造函数
模板
结构alignas(16)vec{
联合{
商店街;
结构{Tx;Ty;Tz;Tw;};
};
内联显式constexpr vec()noexcept:
x{0},y{0},z{0},w{0}{
}
};
//这是支持SSE的版本,我们不能使用
//constexpr因为_mm_setzero_ps,所以让我们删除它。。。
模板
内联向量::向量()无例外:
st(_mm_setzero_ps()){
}
GCC编译它没有问题,但是clang抱怨“constexpr声明之后是'vec'的非constexpr声明”。我想知道哪个编译器做得对,为什么。。?(到目前为止,我无法测试MSVC)
编辑:因为人们对复制和粘贴错误非常挑剔,所以我更正了代码以便编译。如标准草案7.1.5中的注释所述,它似乎是有效的代码 7.1.5 constexpr说明符[dcl.constexpr] 1 constexpr说明符仅适用于变量或变量的定义 变量模板,函数或函数模板的声明, 或者声明一个文本类型的静态数据成员(3.9)。如果 函数或函数模板的任何声明都有一个constexpr 说明符,则其所有声明都应包含constexpr 说明符。[注意:显式专门化可以不同于 关于constexpr说明符的模板声明。-结束 注][注:函数参数不能声明为constexpr.-end 注]
所以gcc似乎是正确的 如标准草案7.1.5中的注释所述,它似乎是有效代码 7.1.5 constexpr说明符[dcl.constexpr] 1 constexpr说明符仅适用于变量或变量的定义 变量模板,函数或函数模板的声明, 或者声明一个文本类型的静态数据成员(3.9)。如果 函数或函数模板的任何声明都有一个constexpr 说明符,则其所有声明都应包含constexpr 说明符。[注意:显式专门化可以不同于 关于constexpr说明符的模板声明。-结束 注][注:函数参数不能声明为constexpr.-end 注]
所以gcc似乎是正确的 目前,每个编译器在编译时都会遇到问题。忘记语法错误,MSVC也不允许。但是,显式专门化
vec
确实允许您编写非constexpr构造函数。看起来编译器之间的比例相当:Clang和MSVC拒绝它,GCC和EDG前端在严格模式下接受它。我倾向于认为它应该被拒绝:它是类模板成员的显式专门化,用于该模板的隐式实例化。类模板的隐式实例化涉及实例化成员函数的声明,因此constepr
已经存在。[14.7.3p6]中的标准中有一个有点相关的例子(涉及enum
s,但我认为原理是一样的)。这里没有真正的理由使用专门化。只需要一个委托构造函数。@T.C.但是我想在这里做编译器的工作(有3个方法体而不是2个),如果我添加更多的专门化(例如vec.Not quite),它会变得非常混乱。标记分派解决方案不会改变以下事实:在模板的所有实例化中,默认构造函数仍然是constexpr。对于vec
,实例化的默认构造函数定义不满足constexpr构造函数的要求(它委托给非constexpr构造函数),因此它不能出现在常量表达式中,但仍被视为constexpr。根据[7.1.5p6]的规定,这是允许的,只要存在至少一个其他模板参数组合,并且专门化确实满足这些要求。目前,每个编译器在编译这些参数时都会遇到问题。忘记语法错误,MSVC也不允许。但是,显式专门化vec
确实允许您编写非constexpr构造函数。看起来编译器之间的比例相当:Clang和MSVC拒绝它,GCC和EDG前端在严格模式下接受它。我倾向于认为它应该被拒绝:它是类模板成员的显式专门化,用于该模板的隐式实例化。类模板的隐式实例化涉及实例化成员函数的声明,因此constepr
已经存在。[14.7.3p6]中的标准中有一个有点相关的例子(涉及enum
s,但我认为原理是一样的)。这里没有真正的理由使用专门化。只需要一个委托构造函数。@T.C.但是我想在这里做编译器的工作(有3个方法体而不是2个),如果我添加更多的专门化(例如vec.Not quite),它会变得非常混乱。标记分派解决方案不会改变以下事实:在模板的所有实例化中,默认构造函数仍然是constexpr。对于vec
,实例化的默认构造函数定义不满足constexpr构造函数的要求(它委托给非constexpr构造函数),因此它不能出现在常量表达式中,但仍被视为constexpr。根据[7.1.5p6],这是允许的,只要存在至少一个其他模板参数组合,且专门化确实满足要求。这里的问题是vec
是隐式的