标记为 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/