【发布时间】:2015-01-05 21:41:10
【问题描述】:
#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() 以这种方式工作而没有提供替代方案?
我在这里做的是根本错误的事情还是我不明白的事情?
【问题讨论】:
-
...
forward_as_tuple返回std::tuple<Types&&...>。您希望forward_as_tuple(0)返回什么类型?什么Types...比int更正确?即,您已经证明会发生什么:您期望发生什么(对于每一行)。它用于完美转发:它返回引用或右值引用的元组。可以写一个存储右值的,它不是很长,如果你想要的话。 -
你不能拥有
constexpr int&& var = ..。 -
如果我通过了
std::forward_as_tuple(1,x,std::move(y)),我会期待std::tuple<int,X&,Y>。我不明白为什么std::forward_as_tuple认为tuple<int&&, X& &&, Y&&>在某种程度上更有用或更正确,并且不提供forward_as_tuple在文字上有效的版本。换句话说,forward_as_tuple似乎并没有正确转发。 -
因为能够命名类型并不意味着创建该类型的实例是合法的。