何时“cons-by-reference”或“pass-by-reference”参数与constexpr兼容?

时间:2012-02-13 03:23:30

标签: c++ c++11 pass-by-reference constexpr

标记为constexpr的函数应该是不可变的纯函数。从"std::max() and std::min() not constexpr"帖子中,您无法将const-reference输入重新引导为输出,因为这将要求参数具有持久性。但是你可以通过const - 参考来获取参数,只要你不重新引用它吗?

// Is this still constexpr?
// (Assuming that std::complex is constexpr-safe, as it's supposed to be.)
constexpr
int  MySum( std::complex<double> const &a, std::complex<double> const &b )
{ return static_cast<int>( a.real() + b.real() ); }

相反,您是否可以将const-reference返回到constexpr启用类型的子对象?

template <typename T>
class MyComplex
{
    T  c_[ 2 ];
public:
    constexpr MyComplex( T r = T(), T i = T() )
    : c_{ r, i }
    {}

    // Is this actually constexpr?
    constexpr T const &  operator[]( unsigned l ) //const
    { return c_[ l ]; }

    // Can't be constexpr
    T &  operator[]( unsigned l )  { return c_[ l ]; }
};

或者甚至子对象返回都必须按值?

(对不起,如果这是基本的,但我发现的一切都围绕这一点跳舞,而不是真正的确定。)

2 个答案:

答案 0 :(得分:3)

标准非常清楚constexpr函数允许的内容:

§7.1.5 [dcl.constexpr] p3

  

constexpr函数的定义应满足以下约束条件:

     
      
  • [...]
  •   
  • 其返回类型应为字面类型;
  •   
  • 每个参数类型都应为文字类型;
  •   
  • [...]
  •   

§3.9 [basic.types] p10

  

类型是文字类型,如果它是:

     
      
  • 标量类型;或
  •   
  • 参考类型;
  •   
  • 具有以下所有属性的类类型(第9条):
  •   
  • 它有一个简单的析构函数,   
        
    • 每个构造函数调用和非静态数据的brace-or-equal-initializers中的full-expression   成员(如果有的话)是常量表达式(5.19),
    •   
    • 它是聚合类型(8.5.1)或至少有一个constexpr构造函数或构造函数模板   这不是复制或移动构造函数,
    •   
    • 它包含所有非静态数据成员和文字类型的基类;或
    •   
  •   
  • 一个文字类型数组。
  •   

因此,是的,你可以有引用参数,甚至是引用非常量参数。 constexpr函数的参数以另一种方式受到限制。完整,详尽的列表可以在§5.19 [expr.const] p2下找到。以下是constexpr声明函数不再如此的摘录 - constexpr

  

条件表达式核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但逻辑AND的子表达式(5.14) ,不考虑未评估的逻辑OR(5.15)和条件(5.16)操作[注意:重载运算符调用函数。 -end note ]:

(关于逻辑运算符的最后一点只是意味着它的未评估部分(由于短路评估)不是确定函数是否真正constexpr的操作的一部分。)

  
      
  • [...]
  •   
  • 动态演员(5.2.7);
  •   
  • a reinterpret_cast(5.2.10);
  •   
  • 伪析构函数调用(5.2.4);
  •   
  • 递增或递减操作(5.2.6,5.3.2);
  •   
  • 一个typeid表达式(5.2.8),其操作数是多态类类型;
  •   
  • a new-expression (5.3.4);
  •   
  • a delete-expression (5.3.5);
  •   
  • 减法(5.7),其中两个操作数都是指针;
  •   
  • 关系(5.9)或相等(5.10)运算符,其中未指定结果;
  •   
  • 作业或复合作业(5.17);或
  •   
  • [...]
  •   

答案 1 :(得分:1)

Core issue 1454的决议改变了约翰内斯在回答the std::max question时所引用的规则。根据该问题的当前解决方案(由g ++和clang实现),constexpr函数可以通过引用返回它们可以计算的任何左值。