2011-01-28 13 views
9

タプルの算術演算子オーバーロードを処理中です。オペレータは、その個々の要素のそれぞれに対して操作を実行するためにタプルを反復処理する。ここではオペレータの定義です+ =:C++ - タプルと型の解と定数のパラメータの比較

template< typename... Ts, std::size_t I = 0 > 
inline typename std::enable_if< I == sizeof... (Ts), std::tuple<Ts...>& >::type operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return lhs; 
} 

template< typename... Ts, std::size_t I = 0 > 
inline typename std::enable_if< I != sizeof... (Ts), std::tuple<Ts...>& >::type operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    std::get<I>(lhs) += std::get<I>(rhs); 
    return operator +=< Ts..., I + 1 >(lhs, rhs); 
} 

私がオペレータに電話をしようとすると、残念ながら、GCC 4.6は、それが使用すべき過負荷か決定することはできません。たとえば:std::enable_if条件が不適切な呼び出しを拒否しなければならないので、奇妙である

:/Workspace/raster/main.cpp:833:7: instantiated from here 
C:/Workspace/raster/main.cpp:809:45: error: no matching function for call to 'operator+=(std::tuple<int, int, int, int>&, const std::tuple<int, int, int, int>&)' 
C:/Workspace/raster/main.cpp:809:45: note: candidates are: 
C:/Workspace/raster/main.cpp:800:151: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I == sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&) 
C:/Workspace/raster/main.cpp:806:83: note: template<class ... Ts, unsigned int I> typename std::enable_if<(I != sizeof (Ts ...)), std::tuple<_TElements ...>&>::type operator+=(std::tuple<_TElements ...>&, const std::tuple<_TElements ...>&) 

std::tuple< int, int, int, int > a = std::make_tuple(1, 2, 3, 4), b = std::make_tuple(5, 6, 7, 8); 
a += b; 

は、次のエラーを生成します。今のところ、私は実際に私の前の実装だった次の回避策を持っています。上記のバージョンは、実際には単純化の試みです。

template< std::size_t I, typename... Ts > 
inline typename std::enable_if< I == sizeof... (Ts), std::tuple<Ts...>& >::type assignadd_impl(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return lhs; 
} 

template< std::size_t I, typename... Ts > 
inline typename std::enable_if< I != sizeof... (Ts), std::tuple<Ts...>& >::type assignadd_impl(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    std::get<I>(lhs) += std::get<I>(rhs); 
    return assignadd_impl< I + 1, Ts... >(lhs, rhs); 
} 

template< typename... Ts > 
inline std::tuple<Ts...>& operator +=(std::tuple<Ts...>& lhs, const std::tuple<Ts...>& rhs) 
{ 
    return assignadd_impl< 0, Ts... >(lhs, rhs); 
} 

これは期待通りにコンパイルされ、動作します。単純化されたバージョンではコンパイルが拒否されるのはなぜですか?ありがとう。

+0

'I'テンプレートパラメータを、最初のコードサンプルの先頭に移動すると、2番目のコードサンプルのように動作します。それは何か変わるのだろうか? –

+0

@Jeremiah Willcock - 残念ながら、テンプレートパラメータの順序を変更するなど、さまざまなバリエーションを試しましたが、すべて同じエラーが発生します。 – pmjobin

答えて

4

明示的に指定されたテンプレート引数を関数またはクラステンプレートに使用するには、テンプレートパラメータパック全体がテンプレートパラメータリスト全体の末尾に表示されている必要があります。 Ts...をテンプレートパラメータリストの最後に移動し、呼び出しを適切に変更するとコードが機能します。 the current C++0x draftの14.8.2.1節では、テンプレートパラメータリストの最後にないパラメータパックを関数呼び出しから推測することはできません(元のコードは失敗します)。すべてのテンプレート引数を明示的にすべてoperator+=に指定するSFINAEエラーが発生します。 A previous questionにはそれを禁止する正確なテキストへのリンクがあります。 IBM's documentationはそれもエラーであると言います。

+0

本当にうまくいきます。私は元のテストで何がうまくいかなかったのか分からない。それでも、ありがとう。 :) – pmjobin

関連する問題