c++ - "return-by-reference"或 "pass-by-reference"参数何时与 constexpr 兼容?

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

标记为 constexpr 的函数应该是不可变的纯函数。来自 "std::max() and std::min() not constexpr"发布后,您无法将常量引用输入重新引导为输出,因为这需要参数具有永久性。但是,只要不重新引导它,您可以通过 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() ); }

相反,您可以返回对启用 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 ]; }
};

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

(抱歉,如果这是基本的,但我发现的所有内容都围绕这一点跳舞,但实际上并没有确定。)

最佳答案

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

§7.1.5 [dcl.constexpr] p3

The definition of a constexpr function shall satisfy the following constraints:

  • [...]
  • its return type shall be a literal type;
  • each of its parameter types shall be a literal type;
  • [...]

§3.9 [基本类型] p10

A type is a literal type if it is:

  • a scalar type; or
  • a reference type; or
  • a class type (Clause 9) that has all of the following properties:
  • it has a trivial destructor,
    • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19),
    • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
    • it has all non-static data members and base classes of literal types; or
  • an array of literal type.

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

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [ Note: An overloaded operator invokes a function. —end note ]:

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

  • [...]
  • a dynamic cast (5.2.7);
  • a reinterpret_cast (5.2.10);
  • a pseudo-destructor call (5.2.4);
  • increment or decrement operations (5.2.6, 5.3.2);
  • a typeid expression (5.2.8) whose operand is of a polymorphic class type;
  • a new-expression (5.3.4);
  • a delete-expression (5.3.5);
  • a subtraction (5.7) where both operands are pointers;
  • a relational (5.9) or equality (5.10) operator where the result is unspecified;
  • an assignment or a compound assignment (5.17); or
  • [...]

关于c++ - "return-by-reference"或 "pass-by-reference"参数何时与 constexpr 兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9255185/

相关文章:

C++ STL vector 迭代器...但出现运行时错误

c++ - 类模板的别名

PHP:通过引用传递给函数的数组?

c++ - 来自 boost::operators 的意外行为

c++ - c/c++ boost - 编译问题

c++ - 从字符串c++中删除单引号字符

c++ - 在事件对象的实现中支持 unique_ptr

C++ vector 的所有组合

java - Java 是 "pass-by-reference"还是 "pass-by-value"?

c++11 : given f(const X&) and f(X&&), 我们需要 f(X&) 吗?