web-dev-qa-db-ja.com

C ++テンプレートコンストラクター

引数のないテンプレートコンストラクターを持つ非テンプレートクラスが必要です。

私が理解している限り、それを使用することは不可能です(デフォルトのコンストラクタ-am I right?)、と競合するため、回避策は次のとおりです:

class A{
   template <typename U> A(U* dummy) {
   // Do something
   }
};

たぶん、これに代わるより良い代替手段(またはより良い回避策)がありますか?

104
Yippie-Ki-Yay

コンストラクターテンプレートを呼び出すときに、テンプレート引数を明示的に指定する方法はないため、引数の推論によって推論する必要があります。これはあなたが言うなら:

Foo<int> f = Foo<int>();

<int>は、そのコンストラクターではなく、Foo型のテンプレート引数リストです。コンストラクターテンプレートの引数リストはどこにもありません。

回避策を講じても、そのコンストラクターテンプレートを呼び出すには、引数を渡す必要があります。あなたが何を達成しようとしているのか明確ではありません。

94
James McNellis

テンプレート化されたファクトリー関数を作成できます。

class Foo
{
public:
    template <class T> static Foo* create() // could also return by value, or a smart pointer
    {
        return new Foo(...);
    }
...        
};
32
KeatsPeeks

私が理解する限り、それを持つことは不可能です(デフォルトのコンストラクタと競合するためです-私は正しいですか?)

あなたは間違っている。競合することはありません。あなたは今までそれを呼び出すことはできません。

template<class...>struct types{using type=types;};
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;

上記のヘルパーを使用すると、値として型を操作できます。

class A {
  template<class T>
  A( tag<T> );
};

tag<T>型は、処理する型以外に状態を持たない変数です。これを使用して、純粋な型の値をテンプレート関数に渡し、テンプレート関数によって型を推測できます。

auto a = A(tag<int>{});

複数のタイプを渡すことができます:

class A {
  template<class T, class U, class V>
  A( types<T,U,V> );
};
auto a = A(types<int,double,std::string>{});

いくつかのポイント:

  • any constructor(テンプレート化されたものを含む)を宣言すると、コンパイラーはデフォルトのコンストラクターの宣言を控えます。
  • コピーコンストラクターを宣言しない限り(クラスXの場合、XまたはX&またはX const &を取る)、コンパイラーはデフォルトのコピーコンストラクターを生成します。
  • T const &またはTまたはT&をとるクラスXのテンプレートコンストラクターを提供する場合、コンパイラはそれにもかかわらず、デフォルトのテンプレート化されていないコピーコンストラクターを生成します。 T = Xの場合、宣言はコピーコンストラクターの宣言と一致するため、そうすべきではありません。
  • 後者の場合、テンプレート化されていないコピーコンストラクターをテンプレート化されたコピーコンストラクターと共に提供することができます。それらは競合しません。 Xが渡されると、非テンプレートが呼び出されます。それ以外の場合、テンプレート

HTH

15
Armen Tsirunyan

これを行うことができます:

class C 
{
public:
    template <typename T> C(T*);
};
template <typename T> T* UseType() 
{
    static_cast<T*>(nullptr);
}

次に、Cをコンストラクタのテンプレートパラメータとして使用して、タイプintのオブジェクトを作成します。

C obj(UseType<int>());

テンプレートパラメーターをコンストラクターに渡すことはできないため、このソリューションは基本的にテンプレートパラメーターを通常のパラメーターに変換します。コンストラクターを呼び出すときにUseType<T>()関数を使用すると、そのパラメーターの目的は、使用する型をコンストラクターに伝えることであることが、コードを見ている人に明らかになります。

これの1つの使用例は、コンストラクターが派生クラスオブジェクトを作成し、それを基本クラスポインターであるメンバー変数に割り当てる場合です。 (コンストラクターは、使用する派生クラスを知る必要がありますが、同じ基本クラスのポインター型が常に使用されるため、クラス自体をテンプレート化する必要はありません。)

2
Tolli

のようなことをしてみてください

template<class T, int i> class A{

    A(){
          A(this)
    }

    A( A<int, 1>* a){
          //do something
    }
    A( A<float, 1>* a){
         //do something
    }
.
.
.
};
0
user2616927

回避策は次のとおりです。

AのテンプレートサブクラスBを作成します。Aのコンストラクターで、構築のテンプレート引数に依存しない部分を実行します。 Bのコンストラクターでテンプレート引数に依存する部分を実行します。

0
Syncopated