为什么`std :: forward_as_tuple(1)`不是一个常量表达式?

时间:2015-01-05 21:41:10

标签: c++ c++14 stdtuple

#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(即使它是由文字初始化的),也就是创建对a的引用临时或他们的forward_as_tuple()的实现不是(尽管C ++ 14标准确实证明了这一点)。

我正在处理一些大量使用std::tupleconstexpr的代码。我可以将std::forward_as_tuple()定义为constexpr,但我无法理解为什么forward_as_tuple(0)会返回tuple<int&&>,根据clang创建的引用暂时使它不是constexpr。替代方案无法满足我的需求 - std::make_tuple()无法用于完美转发,而std::tie无法存储文字值。 修改:为什么std::forward_as_tuple()以这种方式工作而不提供替代方案?

我在这里做了一些根本错误的事情,还是有些我不明白的事情?

1 个答案:

答案 0 :(得分:0)

std::forward_as_tuple以这种方式工作,因为它被指定返回完整转发的参考元组。如果您想要一个在使用std::tuple<int,X&,Y>1x进行调用时返回std::move(y)的函数,请写一个:

template <typename...Ts>
constexpr std::tuple<Ts...> foo(Ts&&...ts) {
  return std::tuple<Ts...>{std::forward<Ts>(ts)...};
}

DEMO