2012-04-25 12 views
5

私のようなクラスを考えていた:デフォルトコンストラクタを条件付きで定義するにはどうすればよいですか?

template < typename ...Whatever > 
class MyClass 
{ 
public: 
    static constexpr bool has_default_ctr = Something; 

    // I want this only if "has_default_ctr" is "true". 
    MyClass(); 

    //... 
}; 

私は(引数はありませんので)私はこのためにコンストラクタテンプレートとstd::enable_ifを使用することができるとは思いません。私が間違っている?そうでない場合は、これを行うための他の方法がありますか?

+0

簡単な考え方 - あなたはデフォルト値を持つ引数を持つ 'enable_if'とコンストラクタを試しましたか? –

+2

なぜあなたはこれをやりたいのですか? –

+0

さて、これは不可能だと正直思っていましたが、私は訂正して答えを削除しました。しかし、これは大きな反パターンではありませんか? – verhage

答えて

-1

あなたは貴様の引数

MyClass(){ 

} 
MyClass(int num){ 

} 
MyClass(String s){ 
} 

、あなたは簡単な書き込みやクラスを返すと、内部の状況を書き込み、静的機能することができてdiferentのコンストラクタを使用することができます。

static chooseContructor(/*parameters*/){ 
if(/*something*/){ 
    return new MyCLass(); 
} 
else if(/*something else*/){ 
    return new MyClass(int num); 
} 
else if{ 
    return new MyClass(String s); 
} 
} 

などなど... そのようなものは、半自動コンストラクターチューザーを与えるでしょう

+0

これは、 'MyClass'にデフォルトで構成可能でないメンバーがあると失敗します。 –

10

C++ 11は、(信頼できる)使用を可能にしますテンプレート引数で3210スタイルのSFINAE:

template< 
    // This is needed to make the condition dependent 
    bool B = has_default_ctr 
    , typename std::enable_if<B, int>::type = 0 
> 
MyClass(); 

// When outside of class scope: 
// have to repeat the condition for out-of-line definition 
template<bool B, typename std::enable_if<B, int>::type = 0> 
MyClass::MyClass() 
/* define here */ 

でC++ 03あなたがデフォルトしたパラメータで単項のコンストラクタを使用していた可能性 - デフォルトのパラメータは、コンストラクタはまだデフォルトコンストラクタとしてカウントすることを意味します。

+0

私の神の男はこのトリックは私にとってとても便利です。私はstd :: enable_ifを認識していましたが、その方法を使用することはありません。 –

+0

これはコンパイル時にエラーが発生すると思います。私が何かが欠けていない限り、 'typename std :: enable_if :: type = 0'は' B = true'のとき 'void = 0'に解決されませんか? 'class C = typename std :: enable_if :: type'が動作します。 –

+0

@ void-pointer置換は 'int = 0'になります。 –

0

条件に応じてクラスの定義を変えるには、依存関係の計算をテンプレートの引数に入れます。

// primary template, no default constructor unless Something is true 
template< typename T, bool has_default_ctr = Something > class MyClass { 
    // as you had it, with no default constructor 
}; 

// you want MyClass<T,true> to be just like MyClass<T,false> 
// but with a default constructor: 
template< typename T > class MyClass<T,true> : public MyClass<T,false> { 

    MyClass() : MyClass<T,false>(/* chosen constructor args */) { etc; } 

    using MyClass<T,false>::MyClass<T,false>; 
}; 

あなたがC++ 11を持っていない場合は、usingコンストラクタの継承を使用することはできません、あなたはそのすべてのコンストラクタを再宣言して、基本クラスに沿ってその引数を転送する必要があります。

これはフィンガー・ツー・キーボードなので、私はコンパイラを使いませんので、軽微な構文のgoofsが多少ありそうです。

+0

@jhill VS11でこのコンパイルを行うことはできません。 constexprのためのサポート無し – Ghita

+0

これはコンパイルされません。テンプレート<型名T、ブールhas_default_ctr> クラスMyClassの { }; テンプレート<型名T、真> MyClassクラス:公共MyClassの { MyClassの() {} }; – Ghita

1

デフォルトのパラメータを持つ溶液は、コメントに記載されているので、あなたが

template < typename ...Whatever > 
class MyClass 
{ 
public: 
    static constexpr bool has_default_ctr = Something; 

    // I want this only if "has_default_ctr" is "true". 
    MyClass() 
    { 
     static_assert(has_default_ctr, "Not Default Constructible"); 
    } 

    //... 
}; 
1

のような単純な何かを行うことができますが、私はそれを行う方法を見つけ出すためにかなりの時間を必要としては、(私のイネーブラクラスはプライベート作ら、これは動作しません)、ここで提案された解決策は、ケースには誰もがそれを探しています:

class MyClass { 
public: 
    // if constructor is supposed to be public, 
    // this helper class must be public as well! 
    struct Enabler {}; 

    template <class U = Enabler> 
    MyClass (std::enable_if_t<has_default_ctr, U> = Enabler {}) 
    { 
     // whatever 
    } 
}; 
0

は、ここで私は、最近使用したものです。データメンバがデフォルトのコンストラクタをサポートしている場合は、デフォルトのコンストラクタを持つクラステンプレートが必要でした。それ以外の場合は、デフォルトのコンストラクタはコンパイルしません。

クラステンプレートはテンプレートタイプパラメータを定義し、クラスはそのようなタイプのデータメンバーを定義します(空のベースクラス最適化を使用できるため、継承を使用するバリアントも魅力的かもしれません)。データメンバのデフォルトコンストラクタは、クラスのデフォルトコンストラクタによって自動的に呼び出されます。データメンバの型にデフォルトのコンストラクタがない場合、コンパイルは失敗します。それ以外の場合は成功します。ここにコードがあります:

#include <string> 
template <typename Data> 
class Demo 
{ 
    Data d_data; 

    public: 
     Demo() = default;  // OK when used and Data has a default 
           // constructor. 

     Demo(Data const &data) // Exampe of an additional constructor 
     : 
      d_data(data) 
     {} 

     // ... 
}; 

struct WithoutDefault 
{ 
    WithoutDefault(int) 
    {} 
}; 

int main() 
{ 
    Demo<std::string> withString; 
    // Demo<NoDefault> nope;    // won't compile 

    WithoutDefault nod(10); 
    Demo<WithoutDefault> nodefault(nod); // OK 
}