2016-10-13 8 views
2

私は、次のような問題があります:あなたは上記を参照できるように、私はテンプレート引数として期待していたクラスAを実装しようメンバ関数の実装

template< typename T, size_t N, size_t... N_i > 
class A 
{ 
    public: 

    // ... 

    // first implementation 
    template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 > 
    A<T, N_i...> operator[](size_t i) 
    { 
     A< T, N_i... > res{ ... }; 

     return res; 
    } 

    // second implementation 
    template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M==1, size_t >::type = 0 > 
    T operator[](size_t i) 
    { 
     return ... ; 
    } 
}; 

をタイプT(例えばintまたはfloat)およびsizeof...(N_i)+1 -many size_t。戻り型A < T, N_i... > の場合sizeof...(N_i)+1 > 1ため

  • 一の実装:

    通過size_tの数に依存し(すなわちsizeof...(N_i)+1)、私は異なる結果型を持つメンバ関数operator[](size_t)に異なる実装を使用します

  • の場合はsizeof...(N_i)+1 == 1、戻り値のタイプがT の場合(コード内では「第2の実装」と呼ばれます)のいずれかを使用します(コードでは「第1の実装」と呼ばれます)。

残念ながら、これはどのように実装できるのかわかりません。上記の解決方法は機能しません。誰にもアイデアはありますか?

事前に感謝します。

答えて

2

A<T, N_i...>N_i空には無効です。`

template <typename, std::size_t ...> 
struct PopFrontA 
{ 
    using type = void; // Dummy type for A<T, N> 
}; 

template< typename T, std::size_t N, std::size_t... N_i > class A; 

template <typename T, std::size_t N, std::size_t N2, std::size_t ... Ns> 
struct PopFrontA<T, N, N2, Ns...> 
{ 
    using type = A<T, N2, Ns...>; 
}; 

template <typename T, std::size_t ... Ns> 
using PopFrontA_t = typename PopFrontA<T, Ns...>::type; 

そして、あなたは` をインスタンス化したら、その後

// first implementation 
template< size_t M = sizeof...(N_i)+1, typename std::enable_if< M!=1, size_t >::type = 0 > 
PopFrontA_t<T, N, N_i...> 
operator[](size_t i) 
{ 
    A< T, N_i... > res{ /*...*/ }; 

    return res; 
} 

Demo

+0

ありがとう! 'A 'が空の 'N_i'に対してSFINAEエラーを引き起こさない理由が分かりますか? –

+1

@abraham_hilbert: 'A 'はメソッドのテンプレートパラメータに依存しません。 'A 'は、メソッドのテンプレートパラメータの値に対して無効です。 – Jarod42

2

あなたは

return T{} ; 

A< T, N_i... > res{ }; 

return ... ; 

A< T, N_i... > res{ ... }; 

を変更した場合十分ではありませんか?

--- EDIT ---

番号:(!ありがとう)Jarod42で指摘したように、十分ではありません。

だから私はあなたがAを専門にしたくない場合は、あなたがAのサブ構造体を追加することができますSFINAE

#include <iostream> 
#include <type_traits> 

template< typename, size_t...> 
class A; 

template< typename T, size_t N, size_t... N_i > 
class A<T, N, N_i...> 
{ 
    public: 
     template <typename Next = typename std::conditional<sizeof...(N_i), 
              A<T, N_i...>, T>::type> 
     Next operator[] (size_t i) 
     { return Next{}; } 
}; 

int main(int argc, char* argv[]) 
{ 
    A<int, 2, 4> a; 

    std::cout << a[1][2] << std::endl; 

    return 0; 
} 

の使用を避けるために、クラステンプレートの特殊化とstd::conditionalに基づいて、以下の解決策を提案汚い仕事をしなさい。

#include <iostream> 
#include <type_traits> 

template< typename T, size_t N, size_t... N_i > 
class A 
{ 
    template <typename U, size_t ... O_i> 
     struct Next 
     { using type = A<U, O_i...>; }; 

    template <typename U> 
     struct Next<U> 
     { using type = U; }; 

    public: 
     using next_t = typename Next<T, N_i...>::type; 

     next_t operator[] (size_t i) 
     { return next_t{}; } 
}; 

int main(int argc, char* argv[]) 
{ 
    A<int, 2, 4> a; 

    std::cout << a[1][2] << std::endl; 

    return 0; 
} 
+0

あなたはエラーになります。 回避策として、あなたは間接を使用することができます。 [デモ](http://coliru.stacked-crooked.com/a/70c3a96907dc600f) – Jarod42

+0

@ Jarod42 - D'oh!あなたが正しい;ありがとう。 – max66