2015-01-05 4 views
3
#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는 성공하지만 gcc 4.9 (우분투 제공) 및 clang 모두 1 ~ 3 행은 컴파일되지 않습니다. 그들은 변수가 constexprs에 의해 초기화되지 않는다고 불평하고 xconstexpr이 아니며 (리터럴로 초기화되었지만) 임시 참조를 생성하거나 forward_as_tuple()의 구현이 그렇지 않습니다 (C++ 14 표준이 이것을 보장합니다).`std :: forward_as_tuple (1)`이 상수 표현이 아닌 이유는 무엇입니까?

std::tupleconstexpr을 많이 사용하는 코드를 작성 중입니다. 나는 을 constexpr으로 정의하지 않고 돌아올 수는 있지만, forward_as_tuple(0)tuple<int&&>을 반환하는 이유를 이해할 수 없다. 이는 clang에 따르면 constexpr이 아닌 임시 참조를 작성한다. 대안은 내가 필요로하는 것에 대해 작동하지 않습니다. std::make_tuple()은 완벽한 전달에 사용할 수없고 std::tie은 리터럴 값을 저장할 수 없습니다. 편집 :std::forward_as_tuple()이 대체 방식을 제공하지 않고 이러한 방식으로 작동하는 이유는 무엇입니까?

내가 근본적으로 뭔가 잘못하고있는 것입니까, 아니면 이해할 수없는 것이 있습니까?

+0

을 ...''표준 : : 튜플 을'반환 forward_as_tuple'. 'forward_as_tuple (0)'이 리턴 할 타입은 무엇입니까? '유형 ... '이'int'보다 더 옳은가? 즉, 어떤 일이 일어 났는지 보여주었습니다. 각 행마다 어떤 일이 발생할 것으로 예상됩니까? 그것은 완벽한 포워딩을위한 것입니다 : 참조 또는 rvalue 참조의 튜플을 반환합니다. rvalues를 저장하는 것은 쓰여질 수 있으며 원하는 경우 오래 걸리지 않습니다. – Yakk

+0

'constexpr int && var = ..'를 사용할 수 없습니다. – Jarod42

+0

만약'std :: forward_as_tuple (1, x, std :: move (y))'를 통과했다면'std :: tuple '을 기대할 것입니다. 내가 이해할 수없는 것은'std :: forward_as_tuple'이'tuple '가 어떻게 든 더 유용하거나 정확하다고 생각하고'forward_as_tuple'이 리터럴에 유효한 버전을 제공하지 않는 이유입니다. 즉, 'forward_as_tuple'이 실제로 제대로 전달되는 것처럼 보이지 않습니다. – SplinterOfChaos

답변

0

std::forward_as_tuple 완벽한 전달을 위해 참조의 튜플을 반환하도록 지정 되었기 때문에 그렇게 작동합니다. 당신이 1, xstd::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)...}; 
} 

DEMO

+0

그것이 내가 어떻게 말했는지는 확실하지 않지만 이것은 내 질문에 답하지 않습니다. 그래서't = std :: forward_as_tuple (0, x)'가'std :: tuple '를 반환하면'std :: get <0> (t)'는'int &&' std :: get <1> (t)'는'X & &&'를 돌려주고, 다른 함수에 건네 주면 (자) 완전하게 전송됩니다. 하지만't = foo (0, x)'와'std :: get <0> (std :: move (t))','std :: get <1> (std :: move t))'? 그것도 완벽하지 않습니까? – SplinterOfChaos