2016-12-01 3 views
17

コンパイル時の条件が満たされている場合にのみ、typedefを実行します。条件が満たされない場合は、typedefはまったく実行されません。"if(condition)typedef ..."を実行する方法はありますか?

これはC++ 11では可能ですか?

例:

class A { 
    std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1". 
    std::conditional_typedef<false,int,myType2>; // Does nothing at all. 
}; 

私はこの架空のstd::conditional_typedefを探しています。

+3

理論的な 'if(...)typedef ...;'というコード例を提供できますか?特に、typedefが「実行されていない」場合、typedefを使用するコードではどうなりますか? – Quentin

+11

[std :: enable_if](http://en.cppreference.com/w/cpp/types/enable_if) – Danh

+1

条件の特殊化に応じて十分かもしれません... –

答えて

19

したい場合は別の方法ではstdする:: enable_ifを同様の基底クラス

// foo is a light struct (only a typedef or not at all) that can be 
// developed in two versions 

template <bool> 
struct foo; 

template <> 
struct foo<true> 
{ typedef int myType1; }; // or using myType1 = int; 

template <> 
struct foo<false> 
{ }; 

template <bool B> 
struct bar : public foo<B> // B can be a type_traits value derived 
          // from template arguments for bar 
{ 
    // potential complex struct or class, developed only one time 
}; 


int main() 
{ 
    bar<true>::myType1 mt1 { 1 }; 
    // bar<false>::myType1 mt2 { 1 }; error: ‘myType1’ is not a member of ‘bar<false>’ 
} 
+0

継承を使用することは、タスクを解決する非常に自然な方法のようです。 – ManuelAtWork

+1

派生した 'bar'を使わずに' foo :: myType1 mt1 {1} 'を直接使うことはできませんか? – chi

+5

@chi - できます。基本クラス(IMHO)を使用する利点は、typedefのみを使用する(または使用しない)簡単で軽いクラスの2つの異なる特殊化を開発できることです。複雑な複雑な派生クラスの単一バージョンを開発することを許可します。 – max66

15

テンプレートインスタンス化に渡される名前は既に定義されていなければならないため、残念なことに、望ましい構文は使用できません。あなたのケースでは、myType1myType2は、コンパイラの観点から何も名をつけません。しかし、あなたが次のようにstd::enable_ifを使用しようとする可能性が言及した構文を主張していない場合:

#include <type_traits> 

struct A { 
    struct myType1: std::enable_if<true, int> { }; //std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1". 
    struct myType2: std::enable_if<false, int> { }; //std::conditional_typedef<false,int,myType2>; // Does nothing at all. 

}; 

int main() { 
    A::myType1::type i; 
    //A::myType2::type i2; // causes error: no type named 'type' in 'A::myType2' 
    (void)i; 
} 

[live demo]


編集:

さらに別の方法私の頭に浮かんだ(デフォルトテンプレートパラメータを使用して利用する):

#include <type_traits> 

struct A { 
    template <class T = int> 
    using myType1 = typename std::enable_if<true, T>::type; 
    template <class T = int> 
    using myType2 = typename std::enable_if<false, T>::type; 
}; 

int main() { 
    A::myType1<> i; 
    //A::myType2<> j; 
    (void)i; 
} 

[live demo]

2

の専門から渡すことができ、あなたのクラスは、あなたのtypedefを行い、テンプレートから派生している可能性があなた自身の名前を使用し、A :: mytype1 :: typeを行う必要はありません。欠点は、これをたくさんしたい場合は、複数の構造体から降下する必要があるということです。

namespace impl { 
    template<bool, typename> struct A; 
    template<typename T> struct A<true, T>{ typedef T mytype1; }; 
    template<typename T> struct A<false, T> {}; 
} 

struct A : public impl::A<condition, int> { 
    //If condition is met, then ::mytype1 will be defined as a typedef int 
}; 

int main() { 
    A::mytype1 i; //Will fail if condition wasn't met 
} 
関連する問題