2012-03-23 13 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

削減テスト・ケース:彼らは、ボイドのfoo 'のような別のタイプ((タプルの中にいる場合を除きhttp://ideone.com/YA6ao – kennytm

+0

コンパイラはあなたのBsを好きではない –

答えて

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 ...演算子()を含む構造体の控除中に返します。 ...それはアリティがすでに推測されているので... Bsの残りのパラメルを食べることはありません。 –

関連する問題