2012-03-23 4 views
1

저는 튜플을 컴파일 타임리스트로 사용하고 있습니다. How can I have multiple parameter packs in a variadic template?에서 나는 GCC와 Clang 둘 다에서 작동하는 몇 가지 코드로 자신을 대답했지만, Clang은 내가 (내가 생각하기에) 완벽한 전달을 추가 했으므로 컴파일하지 않을 것이다. std::forward<As>(as)...에는 As...as...의 길이가 서로 다르다고 불평합니다. As... 유형이 as... 일 때 어떻게 될 수 있습니까? 매개 변수에 As&&... as입니다.이것은 컴파일러 버그 또는 프로그래머 버그입니까?

void operator()(F&& f, A&& a, As&&... as, Bs&&... bs) 

확실히 가능하다 :

#include <iostream> 
#include <tuple> 

template < typename ... > 
struct two_impl {}; 

// Base case 
template < typename F, 
      typename ...Bs > 
struct two_impl < F, std::tuple <>, std::tuple<Bs...> > { 
    void operator()(F&& f, Bs&&... bs) { 
    f(std::forward<Bs>(bs)...); 
    } 
}; 

// Recursive case 
template < typename F, 
      typename A, 
      typename ...As, 
      typename ...Bs > 
struct two_impl < F, std::tuple< A, As... >, std::tuple< Bs...> > { 
    void operator()(F&& f, A&& a, As&&... as, Bs&&... bs) { 
    auto impl = two_impl < F, std::tuple < As&&... >, std::tuple < Bs&&..., A&& > >(); 
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a)); 
    } 
}; 

template < typename F, typename ...Ts > 
void two(F&& f, Ts&& ...ts) { 
    auto impl = two_impl< F, std::tuple <Ts...>, std::tuple <> >(); 
    impl(std::forward<F>(f), std::forward<Ts>(ts)...); 
} 

struct Test { 
    void operator()(int i, float f, double d) { 
    std::cout << i << std::endl << f << std::endl << d << std::endl; 
    } 
}; 

int main() { 
    two(Test(), 1, 1.5f, 2.1); 
} 

clang -lstdc++ -std=c++0x multiple_parameter_packs.cpp

clang -lstdc++ -std=c++0x multiple_parameter_packs.cpp 
multiple_parameter_packs.cpp:24:50: error: pack expansion contains parameter packs 'As' and 'as' that have different 
     lengths (1 vs. 2) 
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a)); 
              ~~ ~~^
multiple_parameter_packs.cpp:24:5: note: in instantiation of member function 'two_impl<Test, std::tuple<float &&, 
     double &&>, std::tuple<int &&> >::operator()' requested here 
    impl(std::forward<F>(f), std::forward<As>(as)..., std::forward<Bs>(bs)..., std::forward<A>(a)); 
    ^
multiple_parameter_packs.cpp:31:3: note: in instantiation of member function 'two_impl<Test, std::tuple<int, float, 
     double>, std::tuple<> >::operator()' requested here 
    impl(std::forward<F>(f), std::forward<Ts>(ts)...); 
^
multiple_parameter_packs.cpp:41:3: note: in instantiation of function template specialization 
     'two<Test, int, float, double>' requested here 
    two(Test(), 1, 1.5f, 2.1); 
^
1 error generated. 

Compilation exited abnormally with code 1 at Fri Mar 23 14:25:14 
+2

감소 테스트 케이스 : http://ideone.com/YA6ao – kennytm

+0

가'무효 foo는 (같은 다른 종류의 내부가 아니라면 말에 있어야 당신의 조식 –

답변

3

이것은 Clang의 이전 버전의 버그 인 것 같습니다. 이 코드는 libstdC++ 또는 libC++와 함께 트렁크 Clang에서 잘 작동합니다.

$ clang++ multiple_parameter_packs.cpp -std=c++11 -stdlib=libc++ 
$ ./a.out 
1 
1.5 
2.1 
1

와 함께 컴파일 나는이 생각하지 않습니다.

매개 변수 팩은 마지막 인수 여야하며 As&&... as 다음에 다른 팩이옵니다.

+0

매개 변수 팩을 좋아하지 않는 컴파일러 (튜플 , 튜플 )')이 될 필요는 없습니다. 그들이 있지 않으면 자동으로 추론 할 수 없습니다. 명시 적으로 템플릿 매개 변수를 지정하면 템플릿 매개 변수 목록의 첫 번째 팩이 그 시점에 남아있는 템플릿 매개 변수를 모두 얻은 것으로 보입니다. 나중의 팩은 비어있을 것이고, 팩이 아닌 매개 변수가 있다면 템플릿 매개 변수가 남아 있지 않기 때문에 템플릿이 작동하지 않을 것이다 :'template void f(); // f는 결코 인스턴스화 될 수 없다. – bames53

+0

operator()의 함수 매개 변수는 추론 할 수없는 맥락에있다. 컴파일러는 이미 예를 들어. 을 as ... 연산자()가 포함 된 구조체에서 공제하는 동안. As ... Bs의 남은 params를 먹어 버리지 않을 것입니다 ... 왜냐하면 그것은 신의가 이미 추론 되었기 때문입니다. –

관련 문제