2017-04-24 5 views
4

constexpr ifをコンパイル時に分岐したいが、最新のMSVCコンパイラではサポートされていないようだ。次?:要するに代替品の場合は、

template<typename T> 
void MyFunc() 
{ 
    if constexpr(MeetsConditions<T>::value) 
    { 
     FunctionA<T>(); 
    } 
    else 
    { 
     FunctionB<T>(); 
    } 
} 

に代わるものはあります:それは、コンパイラによってサポートされていない場合、私はconstexpr ifをシミュレートすることはできますか?

+3

++ 17機能 – max66

+1

はい、わかっています、最新のMSVCはC++を完全にサポートしていません17。 –

+1

SFINAEはC++を必要としません。[simulate-static_if-with-c11c14](https://baptiste-wicht.com/posts/2015/07/simulate-static_if-with-c11c14.html) – Jarod42

答えて

5

事前C++ 17個の方法の一つがここのような部分テンプレートの特殊化を使用することですなっ:

template <template T, bool AorB> 
struct dummy; 

template <typename T, true> 
struct dummy { 
    void MyFunc() { FunctionA<T>(); } 
} 

template <typename T, false> 
struct dummy { 
    void MyFunc() { FunctionB<T>(); } 
} 

template <typename T> 
void Facade() { 
    dummy<T, MeetsConditions<T>::value>::MyFunc(); 
} 

あなたの場合2つのスペシャライゼーション以上のものが必要です。つまり、enumまたはintegral valueを使用して、必要なすべてのenumを専門にすることができます。

もう一つの方法は、STDを使用することです:: enable_if:

template <typename T> 
std::enable_if<MeetsConditions<T>::value, void>::type 
MyFunc() { 
    FunctionA<T>(); 
} 

template <typename T> 
std::enable_if<!MeetsConditions<T>::value, void>::type 
MyFunc() { 
    FunctionB<T>(); 
} 
4

あなたはそれを昔ながらの操作を行うことができ、タグディスパッチ方法を試してみましたが、テストした:

template<typename T> 
void MyFuncImpl(std::true_type) { 
    FunctionA<T>(); 
} 

template<typename T> 
void MyFuncImpl(std::false_type) { 
    FunctionB<T>(); 
} 

template<typename T> 
void MyFunc() 
{ 
    MyFuncImpl<T>(std::integral_constant<bool, MeetsConditions<T>::value>{}); 
} 
3

if constexprは、C++ 17の機能です。あなたが唯一のC++ 98コンパイラを使用することができた場合は、

実装 - EDIT - C++ 17の前に、C++ 11から始まる、あなたはstd::enable_if

template<typename T> 
typename std::enable_if<true == MeetsConditions<T>::value>::type MyFunc() 
{ FunctionA<T>(); } 

template<typename T> 
typename std::enable_if<false == MeetsConditions<T>::value>::type MyFunc() 
{ FunctionB<T>(); } 

でSFINAEを使用することができますstd::enable_ifのように機能する型の特性は本当に単純です。次の例に

template <bool, typename = void> 
struct enableIf 
{ }; 

template <typename T> 
struct enableIf<true, T> 
{ typedef T type; }; 

を見ると機能が

template<typename T> 
typename enableIf<true == MeetsConditions<T>::value>::type MyFunc() 
{ FunctionA<T>(); } 

template<typename T> 
typename enableIf<false == MeetsConditions<T>::value>::type MyFunc() 
{ FunctionB<T>(); } 
+0

11、それは常にC++にありました。 – Angew

+0

@Angew - あなたの権利:SFINAEではなくC++ 11から利用可能な 'std :: enable_if'です。ありがとう。 Answer – max66

+0

C++ 11がオプションでない場合、常に 'boost :: enable_if'があります。 – Angew

6

if constexprが存在し始めたずっと前に使用されている)実際にいくつかの選択肢があります。

一つは、タグの発送です:

template <class T> 
void Function(std::true_type) 
{ 
    FunctionA<T>(); 
} 

template <class T> 
void Function(std::false_type) 
{ 
    FunctionB<T>(); 
} 

template <class T> 
void MyFunc() 
{ 
    Function<T>(std::integral_constant<bool, MeetsCondition<T>::value>{}); 
} 

もう一つは形質である:

template <bool B> 
struct FunctionTraits; 

template <> 
struct FunctionTraits<true> 
{ 
    template <class T> 
    static void Call() { FunctionA<T>(); } 
}; 

template <> 
struct FunctionTraits<false> 
{ 
    template <class T> 
    static void Call() { FunctionB<T>(); } 
}; 

template <class T> 
void MyFunc() 
{ 
    FunctionTraits<MeetsCondition<T>::value>::Call<T>(); 
} 
4

あなたがC++ 14とブーストを使用している場合は、Hanaを使用することを検討してください。以下のような単純なものでしたSFINAEを検出し、この場合においてのみ、何かを実行する具体的なケースについては、

template<typename T> 
void MyFunc() 
{ 
    hana::eval_if(MeetsConditions<T>::value, 
     [](auto) { FunctionA<T>(); }, 
     [](auto _) { FunctionB<T>(_(exprThatWouldOtherwiseBeAnError)); } 
    ); 
} 

:花を使用して実装され、これは次のようになりますそれは、Cの

template<typename T> 
void MyFunc() 
{ 
    auto maybeDoFunctionA = hana::sfinae([] -> decltype((void) FunctionA<T>()) { 
     FunctionA<T>(); 
    }); 
}