2017-10-05 3 views
1

私はちょっとしたことがないと思っています。実装のためにテンプレート化されたクラスのコンストラクタを特殊化する必要があります。ここで、T =任意のパラメータを持つテンプレートクラスです。申し訳ありませんが私のボキャブスは少しオフです。 基本的には、ギザギザの2D配列を許容する必要があるので、ArEl<ArEl<int>>があり、すべての配列長を事前に初期化したいと考えています。部分クラステンプレートの特殊化で継承を実装するにはどうすればよいですか?

using namespace std; 

template <typename T> 
class ArEl { 
public: 
    ArEl(size_t size = 0) 
     : rSize(size), rArray(rSize ? new T[rSize]() : nullptr) {} 
    ArEl(const ArEl& other); 
    virtual ~ArEl() { delete[] rArray; } 
    void swap(ArEl& first, ArEl& second); 
    void redim(size_t size); 

private: 
    std::size_t rSize; 
    T* rArray; 
}; 

template <typename T, typename T1> 
class ArEl<ArEl<T>> : public ArEl<T1>{ 
    ArEl(size_t size = 0); 
}; 

EDIT:

error: template parameters not deducible in partial specialization: 
class ArEl<ArEl<T>> : public ArEl<T1>{ 

答えて

4

あなたは間違った方法であなたのオブジェクトを専門にしている:私はこのエラーを取得してい

template<typename T, typename T1>は、提供する必要があるデータ型が2つあることを示していますが、テンプレートの特殊化に必要なのは、基本となる配列のデータ型のみです。期待がArEl<ArEl<T>>を専門にするということであれば、これ以上を取るべきではありません。

template<typename T> 
class ArEl<ArEl<T>> { 
    /*Blah Blah Blah*/ 
}; 

継承のための必要性、及び第二のデータ型の必要はありません。

しかし、私は次のようにも付け加えます。まず、この専門化は必要ありません。

ArEl<ArEl<int>> dim2Array(50); 
//I'm assuming ArEl will have a member size() function 
for(size_t index = 0; index < dim2Array.size(); index++) { 
    //I'm assuming ArEl will have an operator[] overload 
    dim2Array[index].redim(30); 
} 
//dim2Array is now 50 int arrays, each of size 30. 

私は必要ないこれ、あなたが意図している機能は、次のようなものを持っていると仮定している:あなたがすべてで専門を書いていない場合は、次のコードはまだそのままで動作するはずです

ArEl<ArEl<int>> dim2Array(50, 30); 
//dim2Array is now 50 int arrays, each of size 30. 

しかし、私があなただったら、私は一人でArElの実装を離れ、代わりに(N-寸法のために、または多分Matrix<T, N>Matrix<T>クラスを書くに投資処理するだろう:私は上に掲載するもののようなテンプレートの特殊代わりにこの種の構文(ArEl<T>を使用して構築できます特に、私があなたがArEl<ArEl<ArEl<int>>>の専門化を書くことに専念しているとは思わないので、特にそうではありません。それぞれのレベルは独自の専門性を必要とします。

3

クラス全体を専門にすることは、すべてのメンバーを専門分野で提供されているメンバーに置き換えることを意味します。あなたはそれを望んでいません。

1つのオプションは、ベースクラスに特殊化が必要なすべてのメンバーを提供することです。BaseForA<T>は特殊化され、A<T>はそれから派生します。

もう1つは、タグのディスパッチを使用することです。次に、タイプパラメータに応じてさまざまなアクションを実行する方法の例を示します。

#include <iostream> 
#include <type_traits> 

template<typename T> 
struct tag {}; 

template<typename T> 
struct A 
{ 
private: 
    template<typename U> 
    A(std::size_t s, tag<A<U>>) 
    { 
     std::cout << "special constructor " << s << "\n"; 
    } 

    A(std::size_t s, ...) 
    { 
     std::cout << "general constructor " << s << "\n"; 
    } 
public: 
    A(std::size_t s = 0) : 
     A(s, tag<T>()) 
    { 

    } 
}; 

int main() 
{ 
    A<int> a; 
    A<A<int>> b; 
    A<A<long>> c; 
    A<long> d; 
} 

Live on Coliru

0

私が正しくあなたを理解していれば、あなたは一般的なバージョンを継承し、それの上に何かを追加するための特殊なバージョンが欲しいです。ここでの問題は、あなたが特殊化したArEl<ArEl<T>>を持っているということです。一般的なバージョンを要求することはできません。

解決策は、汎用バージョンと特殊バージョンを異なるタイプにすることです。

template<typename T, bool D=true> 
class ArEl { ... 

template<typename T> 
class ArEl<ArEl<T>>: 
    public ArEl<ArEl<T>, false> { ... 

しかし、今の問題は、ArEl<T, true>ArEl<T, false>は無関係と互換性がないということです!

解決策は、共通の基本クラスを導入することです。

template<typename T> 
class ArElBase { 
    ... all functionality of ArEl 
}; 

template<typename T, bool D=true> 
class ArEl : public ArElBase<T> { 
    using ArElBase<T>::ArElBase; 
    // nothing more 
}; 

となり、その後は特殊化されていません。

ArElBaseを使用すると、オブジェクトをポインタまたは参照で渡すことができますが、ArElを使用してオブジェクト自体を宣言することができます。

関連する問題