"return-by-reference"或"pass-by-reference"参数何时与constexpr兼容?
When are "return-by-reference" or "pass-by-reference" parameter compatible with constexpr?
标记为constexpr的函数应该是不可变的纯函数。从"std::max()and std::min()not constexpr"的帖子中,您不能将const引用输入重新作为输出,因为这需要参数具有永久性。但是你能通过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
类型的子对象的const引用?
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
constexpr
函数的定义应满足以下约束:
- […]
- 其返回类型应为文字类型
- 其每个参数类型应为文字类型
- […]
§3.9 [basic.types] p10
一个类型是文字类型,如果它是:
- 标量类型;或
- 引用类型或
- 具有以下所有属性的类类型(第9条):
- 它有一个琐碎的析构函数,
- 大括号中的每个构造函数调用和完整表达式或非静态数据的相等初始值设定项成员(如果有的话)是常数表达式(5.19)
- 它是聚合类型(8.5.1),或者至少有一个constexpr构造函数或构造函数模板不是复制或移动构造函数,以及
- 它具有所有非静态数据成员和文本类型的基类;或
- 文字类型的数组
因此,是的,您可以有引用参数,甚至可以引用非常数参数。constexpr
函数的参数以另一种方式受到限制。完整、详尽的列表可在§5.19 [expr.const] p2
下找到。以下是使constexpr
声明的函数不再是constexpr
的摘录:
条件表达式是核心常量表达式
(关于逻辑运算符的最后一位只是意味着它的未评估部分(由于短路评估)不是确定函数是否真的是constexpr
的操作的一部分。)
- […]
- 动态铸造(5.2.7)
reinterpret_cast
(5.2.10)- 伪析构函数调用(5.2.4)
- 递增或递减操作(5.2.6,5.3.2)
- typeid表达式(5.2.8),其操作数是多态类类型
- 一个新表达式(5.3.4)
- a删除表达式(5.3.5)
- 减法(5.7),其中两个操作数都是指针
- 关系运算符(5.9)或等式运算符(5.10),其中未指定结果
- 转让或复合转让(5.17);或
- […]
核心问题1454的解决方案改变了Johannes在回答std::max问题时引用的规则。根据该问题的当前解决方案(由g++和clang实现),constexpr
函数可以通过引用返回它们可以计算的任何左值。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 多成员Constexpr结构初始化
- 条件constexpr函数
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- Visual C++ constexpr Hints
- 如何确认我的constexpr表达式实际上已经在编译时执行
- 为什么constexpr的性能比正常表达式差
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 为什么std::isnan 不是 constexpr?
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 更多constexpr容器是否需要mark_immutable_if_consexpr
- C++从其他 constexpr 创建 lambda 不能按顺序执行 Constexpr
- 码头化的C++应用程序是否向后兼容早期的内核版本
- constexpr上下文中std::initializer_list的验证
- constexpr构造函数需要常量成员函数时出现问题
- 可能的模板和constexpr - 如果不兼容
- 使 C++14 constexpr 函数C++11 兼容
- "return-by-reference"或"pass-by-reference"参数何时与constexpr兼容?