2016-04-14 10 views
0

は、次のコードスニペットを考えてみてくださいクラステンプレートから派生しているかどうかをチェックしますc<F, B>から?型特性は、いくつかのタイプが

例:F = e<D>についてc<F, B>由来するDようFに応じて、いくつかのタイプBあります。

+0

の可能な重複を(http://stackoverflow.com/questions/25845536/trait-to-check-if-some-specialization -f-template-class-is-base-of-specifi) – Orient

+0

もし 'c'ならあなたが作者であれば、テンプレート以外の' class 'クラスから 'c'を派生させるとあなたの人生を楽にすることができますfoo {} 'を実行し、次に' f'が 'foo'から派生したものであるかどうかを' std :: is_base_of'を使って調べます。 –

+1

@ JohannesSchaub-litbはい、私はそのようなe_tagクラスを使うことに決めました。 – 0xbadf00d

答えて

3

この回答は質問に焦点を当てています。タイプF考える

は、どのように私は Fc<F, B>から派生し Bように、いくつかの種類があるかどうかを確認することができますか?

そしてわかりやすくするためのコメント。

Fが何らかのBためc<F, B>に由来する場合形質が確認する必要があります(それはBが何であるかは重要ではありません)。

constexpr機能は、「誘致」と離れて他のタイプからベースc<F, B>を区別するために使用することができます。 ファンクションテンプレートは、deduce types(これは、要件の一部を満たす必要があります(Bを満たす必要があるため)が優先されます。次のような形式のもの...

template <typename F, typename B> 
constexpr bool check_base(C<F, B> &&) { return true; } 

template <typename F> 
constexpr bool check_base(...) { return false; } 

次のサンプルでは、​​使用シナリオが改善され、基本的な動作が示されています。

#include <utility> 
template <typename A, typename B> 
struct C {}; 

template <typename F, typename B> 
constexpr std::true_type check_base_(C<F, B>&&) { return {}; } 

template <typename F> 
constexpr std::false_type check_base_(...) { return {}; } 

template <typename T> 
using check_base = decltype(check_base_<T>(std::declval<T>())); 

template <typename D> 
struct E : C<E<D>, D> {}; 
struct FailF {}; 

int main() 
{ 
    static_assert(check_base<E<int>>()); 
    static_assert(!check_base<FailF>()); 
} 

See the demo here

constexprを削除した場合は、check_base_関数の不要なインライン定義を削除することもできます。

注:溶液/にアクセス基底クラス(すなわちないprivate又はprotected)をアサート前提。基本クラスがprivateの場合、上記のコードはアクセシビリティエラーでコンパイルに失敗します。以下のコードは失敗しません。SFINAEは、コンパイルを続行するために行われます。

Online demo here。 [テンプレートクラスのいくつかの専門は、特定のクラスの基底クラスであるかどうかを確認するために形質]

#include <utility> 
#include <type_traits> 
template <typename A, typename B> 
struct C {}; 

template <typename F, typename B> 
std::true_type check_base_(C<F, B>&&, typename std::enable_if<std::is_convertible<F, C<F,B>>::value>::type* = nullptr); 

template <typename F> 
std::false_type check_base_(...); 

template <typename T> 
using check_base = decltype(check_base_<T>(std::declval<T>())); 

template <typename D> 
struct Example : C<Example<D>, D> {}; 
struct CtorTest : C<CtorTest, int> { CtorTest(int, int) {} }; 
struct PrivateBase : private C<PrivateBase, double> {}; 
struct FailTest {}; 

int main() 
{ 
    static_assert(check_base<Example<int>>(), "fail..."); 
    static_assert(check_base<CtorTest>::value, "fail..."); 
    static_assert(!check_base<PrivateBase>(), "fail..."); 
    static_assert(!check_base<FailTest>(), "fail..."); 
} 
+0

これは固定でも引数であってもいけません。それが疑問の全ポイントです。この処置は 'F'が* some *' B'の 'c 'から派生しているかどうかをチェックするべきです( 'B'は何であるか重要ではありません)。 – 0xbadf00d

+0

これを質問に編集する必要があります。それが疑問であるように、問題には関連していないと思われるDとBの派生語とクラスeへの参照が含まれています。 – Niall

+0

私はこの質問を明確にしました。なぜなら、ある種のものが存在するかどうかチェックするべきだと述べたからです... – 0xbadf00d

関連する問題