Rum*_*rak 24 c++ static-assert language-lawyer copy-elision c++11
我有一个我static_assert的模板结构的移动构造函数.这是否static_assert需要编译器考虑,即使可以复制省略?
这是精简的场景:
#include <type_traits>
template<typename T>
struct X
{
X(X&&) { static_assert(std::is_same<void, T>::value, "Intentional Failure"); }
};
auto impl() -> X<int>;
auto test() -> decltype(impl())
{
return impl();
}
int main()
{
test();
}
Run Code Online (Sandbox Code Playgroud)
GCC和Clang同意评估static_assert并且无法编译.
另一方面,MSCV和ICC编译代码就好了.
有趣的是,当我删除move构造函数的定义时,只需将其声明为:
template<typename T>
struct X
{
X(X&&);
};
Run Code Online (Sandbox Code Playgroud)
GCC和Clang现在也编译代码.因此,所有编译器似乎都同意移动构造函数的定义与复制省略无关.
问题:
如果static_assert复制/移动构造函数中有a ,即使可以复制/移动省略,标准是否要求对其进行评估?
以下内容应该有所帮助。
您不必使用类型推导来说明问题。即使是更简单的例子也有同样的问题:
#include <type_traits>
template <typename T>
struct X
{
X() {}
X(X&&) { static_assert(std::is_same<void, T>::value, "failed"); }
};
int main()
{
X<int> x = X<int>();
}
Run Code Online (Sandbox Code Playgroud)
Clang 和 GCC 不会编译它。MSVC 编译并执行良好。
这表明问题与 odr 使用以及实例化成员函数的定义有关。
14.7.1 [temp.inst] 第 2 段说“[...] 当在需要成员定义存在的上下文中引用专门化时,成员的专门化将被隐式实例化”
3.2 [basic.def.odr] 第 3 段(在注释中)说“[...] 选择用于复制或移动类类型对象的构造函数是 odr 使用的,即使该调用实际上被实现省略了”
3.2 [basic.def.odr] 第 4 段说“每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的一个定义;不需要诊断。”
因此:专业化应该被实例化,并且断言已经触发。
| 归档时间: |
|
| 查看次数: |
785 次 |
| 最近记录: |