2017-07-12 18 views
1

私は関数のテンプレート型をコンパイル時に特定のクラスとそのサブクラスに制限しようとしています。これを実現するために、私はタイプを使用していますと、このようstd::enable_if_tstd::is_base_ofを特色:SFINAEのstd :: enable_if_t&std :: is_base_ofを使ってコンパイル時の継承をチェックする方法は?

template <typename T = std::enable_if_t<std::is_base_of<A, T> > > 

しかし、テンプレートは、まだ継承階層(すなわちint)の一部ではないタイプでコンパイルします。以下は、問題のMCVEです:

class A { 
public: 
    A(float a) : a(a) {} 
    float a; 
}; 
class B : public A{ 
public: 
    B(float a) : A(a) {} 
}; 

template <typename T = std::enable_if_t<std::is_base_of<A, T> > > 
void templateFunction(T a) { 

} 

int main() { 
    templateFunction<A>(A(1.0f)); // OK -> std::is_base_of<A, A> 
    templateFunction<B>(B(1.0f)); // OK -> std::is_base_of<A, B> 

    templateFunction<int>(1); // Should not compile! int is not a subclass of A -> std::is_base_of<A, int> 
    return 0; 
} 

これはエラーなしのVisual Studio 2017の下でコンパイルしますが、テンプレート関数の最後のインスタンス化は、私の理解でコンパイルべきではありません。 私のタイプ特性の使用に問題はありますか、Visual Studio SFINAEの実装に問題がありますか?

答えて

0

enable_ifのご使用は少し奇妙ですが、私は次のことを行っているでしょう:

template <typename T> 
std::enable_if_t<std::is_base_of<A, T>::value> templateFunction(T a) { 

} 

または代わりに:

template <typename T> 
void templateFunction(std::enable_if_t<std::is_base_of<A, T>::value, T> a) { 

} 

でもよりよい解決策を:完全SFINAE忘れる:

template <typename T> 
void templateFunction(T a) { 
    static_assert(std::is_baseOf<A,T>(), "only subclasses, please"); 
} 

編集、説明: enable_if_tをお勧めします条件が満たされた場合にタイプとなるもの(デフォルトはvoid)です。これを適用する

として、あなたの関数は読み:あなたの呼び出しは、まだ偽の場合のテンプレートと一致

// true case: 
template <typename T = void> 
void templateFunction(T a) {} 

// false case: 
template <typename T = nonsense> 
void templateFunction(T a) {} 

は今、私の提案のコードにこれを適用する:ここで

//true case: 
template <typename T> 
void templateFunction(T a) {} 

//false case: 
template <typename T> 
*nonsense* templateFunction(T a) {} 

、関数が偽の場合には全く存在していることができないので、コンパイルエラーを作成します。

関連する問題