正如this page中所解释的,constexpr
构造函数的主体的复合语句,如果它没有删除也没有默认,必须满足constexpr
函数体的约束,也就是说,它可能包含除以下内容之外的任何陈述:
asm
声明goto
声明try
- 阻止似乎标准不限制可能出现的return
语句的数量,而在C ++ 11中,只允许一个语句。
现在,请考虑以下代码:
class Thing
{
public:
// Shouldn't this constructor be fine under both C++11 and C++14?
constexpr Thing ( )
{
return;
}
};
int main ( )
{
Thing a_nice_thing;
}
Clang(3.5, -std = c ++ 14 )编译得很好,但是GCC(4.9.1, -std = c ++ 14 )没有抱怨:
constexpr构造函数没有空体
但是,如果改变了:
class Thing
{
public:
// This constructor is fine under both C++11 and C++14
constexpr Thing ( )
{
static_assert( __cplusplus > 1 , "static_assert isn't the right mechanism to test this, since it wasn't available at earlier versions of the language" );
}
};
int main ( )
{
Thing a_nice_thing;
}
然后在两个编译器下编译都很好。
由于海湾合作委员会抱怨建设者的身体不是空的,不应该在后来的情况下抱怨吗?这种行为是GCC中的一个错误吗? constexpr构造函数是否允许返回语句?
注意:单个return
语句是否真的值得这不是这个问题的范围,虽然有趣并且可能值得另一个。由于样式原因,我将单个return
语句放在主体为空的构造函数上。
答案 0 :(得分:5)
GCC目前是doesn't support C ++ 14的constexpr
版本,所以即使使用-std=c++14
,您仍然可以获得C ++ 11 constexpr
。
对constexpr
构造函数体的C ++ 11限制是(§7.1.5[dcl.constexpr] / p4):
function-body 的复合语句仅包含
- null语句,
- static_assert-声明
typedef
声明和 alias-declarations ,它们没有定义类或枚举,- 使用-声明,
- 和 using-directives ;
(还有很多其他限制;我将报价限制在与问题相关的报价上。)
在C ++ 11中return
构造函数中不允许使用 constexpr
语句,而static_assert
是。{{1}}。
答案 1 :(得分:1)
C ++ 14它改变了,如draft C++14 standard部分所述7.1.5 constexpr说明符
其函数体应为= delete,= default或不包含
的复合语句- asm-definition,
- goto语句,
- 试用版块,或
- 非文字类型或静态或线程存储持续时间的变量的定义 没有执行初始化
并且构造函数必须遵循其他限制:
- 其函数体应为= default,或其函数体的复合语句应满足 constexpr函数的函数体的约束;
- 应初始化每个非变量非静态数据成员和基类子对象(12.6.2);
- 如果该类是具有变体成员的联合(9.5),则其中一个应该被初始化;
- 如果该类是一个类似联合的类,但不是一个联合,它的每个匿名联盟成员都有 变体成员,其中一个应该被初始化;
- 对于非委托构造函数,选择每个构造函数来初始化非静态数据成员和 基类子对象应该是constexpr构造函数;
- 对于委托构造函数,目标构造函数应该是constexpr构造函数。
并且它不会阻止返回语句也不会阻止static_assert
。
在C ++ 11中它包含了限制:
- 其函数体的复合语句仅包含
- 空语句,
- static_assert-declarations
- 未定义类或枚举的typedef声明和别名声明,
- 使用声明,
- 和using-directives
,不允许返回语句。