为什么"std::forward_as_tuple(1)"不是常量表达式?
Why isn't `std::forward_as_tuple(1)` a constant expression?
#include <tuple>
int main() {
static_assert(std::is_same<std::tuple<int&&>,
decltype(std::forward_as_tuple(1))>::value, "");
constexpr int x = 5;
constexpr auto t1 = std::forward_as_tuple(1); // (1)
constexpr auto t2 = std::forward_as_tuple(x); // (2)
constexpr std::tuple<int&&> t3(1); // (3)
constexpr std::tuple<int> t4(1); // OK!
}
在上面的代码中,static_assert通过,但是第 1 行到第 3 行无法同时使用 gcc 4.9(由 ubuntu 提供)和 clang 进行编译。他们抱怨变量不是由constexprs
初始化的,x
不是constexpr
(即使它是由文字初始化的),而是创建对临时的引用,或者他们对forward_as_tuple()
的实现不是(尽管C++14标准确实保证了这一点)。
我正在研究一些大量使用std::tuple
和constexpr
的代码。我可以绕过std::forward_as_tuple()
没有被定义为constexpr
,但我不明白为什么forward_as_tuple(0)
会返回一个tuple<int&&>
,根据clang的说法,它创建了一个对临时的引用,使其不是constexpr。替代方案不适用于我需要的 - std::make_tuple()
不能用于完美的转发,std::tie
也不能存储文字值。编辑:为什么std::forward_as_tuple()
以这种方式工作而不提供替代方案?
我在这里做错了什么根本性的事情,还是有什么我不明白的地方?
std::forward_as_tuple
这样工作,因为它被指定为返回一个引用元组以实现完美转发。如果你想要一个函数在使用 1
、 x
和 std::move(y)
调用时返回 std::tuple<int,X&,Y>
,那么编写一个:
template <typename...Ts>
constexpr std::tuple<Ts...> foo(Ts&&...ts) {
return std::tuple<Ts...>{std::forward<Ts>(ts)...};
}
演示
相关文章:
- 不能在初始值设定项列表中将非常量表达式从类型 'int' 缩小到'unsigned long long'
- 当一个值是非常量但用常量表达式初始化时使用constexpr
- 使用自动推导的 lambda 参数作为常量表达式
- 生成提升::hana::set 的常量表达式问题
- 为什么不能用常量表达式声明数组?
- 不是 lambda 函数中的常量表达式
- 函数调用在常量表达式中必须具有常量值
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 关于在需要常量表达式的上下文中使用的glvalue常量表达式的问题
- 生成 constexpr 字符串表,不能产生常量表达式
- 整体模板参数。错误:在常量表达式中使用'this'
- 如何在满足常量表达式的同时将整数传递给指针,传递给 std::array<double、integer>?
- 编译器错误:函数调用在常量表达式中必须有一个常量值
- 错误:'new'不能出现在常量表达式中
- 我可以写出小于 -0.5 两个 ulps 的常量表达式双精度吗?
- 编译器在传递 const 变量时返回错误:模板参数不是常量表达式
- 为什么我不能在非常量表达式上使用此模板阶乘函数?
- C++ 使用变量而不是常量表达式初始化数组
- 使用函数参数作为常量表达式的一部分 - gcc vs clang
- 片段着色器中的"错误:在 GLSL 1.30 及更高版本中禁止使用非常量表达式索引的采样器数组"