[英]GCC and Clang different behaviors on constexpr constructor
对于这个结构:
struct Wrapper {
int value;
constexpr explicit Wrapper(int v) noexcept : value(v) {}
Wrapper(const Wrapper& that) noexcept : value(that.value) {}
};
而这个功能:
constexpr Wrapper makeWrapper(int v)
{
return Wrapper(v);
}
以下代码无法为Clang(Apple LLVM版本7.3.0)编译,但是对于GCC(4.9+)编译正常,两者都使用-Wall -Wextra -Werror -pedantic-errors
:
constexpr auto x = makeWrapper(123);
Clang抱怨说“非constexpr构造函数'Wrapper'不能用于常量表达式。” 哪个编译器是对的?
铿锵是对的。 它在g ++中工作,因为它会自动删除复制构造函数(RVO)。 如果你传递-fno-elide-constructors
。 g ++也会抱怨。
C ++ 14标准不清楚constexpr
对象中的Copy-Elision。
[class.copy / 32] ... (部分转载于此处)
当满足复制/移动操作的省略标准时......即使呼叫被省略,所选构造函数也必须是可访问的。
直到我们知道accessible
的定义? 我们可以假设g ++也是正确的吗?
对象声明中使用的constexpr说明符将对象声明为const。 这样的对象应具有文字类型并应初始化。 如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式([expr.const])。 否则,或者如果在引用声明中使用constexpr说明符,则其初始值设定项中出现的每个全表达式都应为常量表达式。
Dietmar Kuhl的回答告诉我们未来的发展方向。
演示:
struct Wrapper {
int value;
constexpr explicit Wrapper(int v) noexcept : value(v) {}
Wrapper(const Wrapper& that) noexcept : value(that.value) {}
};
constexpr Wrapper makeWrapper(int v)
{
return Wrapper(v);
}
int main()
{
constexpr auto x = makeWrapper(123);
}
编译
g++ -std=c++14 -Wall -pedantic -fno-elide-constructors main.cpp && ./a.out
在这里看到它
两个编译器都是对的。
constexpr
函数和初始化程序的规则表明不能调用非constexpr
函数。
复制省略的规则表明,未指定非constexpr
复制构造函数是否被调用。
唯一的结论是,未指定函数和初始化程序是否满足constexpr
的要求。 如果他们这样做,那么编译器必须接受它。 如果他们不这样做,那么编译器必须诊断问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.