Why isn't `std :: forward_as_tuple (1)` 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!
}
In the above code, this static_assert goes through, however lines 1 through 3 will not compile with both gcc 4.9 (shipped with ubuntu) and clang. They complain that variables are not initialized constexprs
, that x
it is not constexpr
(even if it is initialized with a literal), that is, it creates a reference to a temporary, or that their implementation forward_as_tuple()
is equal (although the C ++ 14 standard guarantees this).
I am working on some code that makes heavy use of std::tuple
and constexpr
. I can get around std::forward_as_tuple()
not being defined as constexpr
, but I can't figure out why forward_as_tuple(0)
will return tuple<int&&>
, which, according to clang, creates a reference to the temporary creation of this non constexpr. The alternatives don't work for what I need - std::make_tuple()
cannot be used for perfect forwarding, and std::tie
cannot store literal values. Edit: Why std::forward_as_tuple()
works this way and doesn't offer alternatives?
Am I doing something fundamentally wrong here or is there something I don't understand?
source to share
std::forward_as_tuple
works like this because it is defined to return a tuple of links for perfect forwarding. If you want a function that returns std::tuple<int,X&,Y>
when called with 1
, x
and std::move(y)
then write one:
template <typename...Ts>
constexpr std::tuple<Ts...> foo(Ts&&...ts) {
return std::tuple<Ts...>{std::forward<Ts>(ts)...};
}
source to share