constexpr构造函数是否允许返回语句?

时间:2014-09-19 20:26:16

标签: c++ gcc constructor c++14 constexpr

正如this page中所解释的,constexpr构造函数的主体的复合语句,如果它没有删除也没有默认,必须满足constexpr函数体的约束,也就是说,它可能包含除以下内容之外的任何陈述:

  • asm声明
  • goto声明
  • a 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语句放在主体为空的构造函数上。

2 个答案:

答案 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

,不允许返回语句。