2016-04-14 89 views
0

请考虑下面的代码片段得出:型特征,以检查是否有些类型是从类模板

template<class A, class B> 
class c {}; 

template<class D> 
class e 
    : public c<e<D>, /* some type depending on D */> 
{ } 

给定一个类型F,我怎么能检查是否有某种类型的B这样F推导来自c<F, B>

示例:对于F = e<D>有某种类型的B取决于D使得Fc<F, B>的。

+0

的可能的复制[性状,以检查是否模板类的一些专业化是基类特定类的](http://stackoverflow.com/questions/25845536/trait-to-check-if-some-specialization -of-template-class-is-base-class-of-specifi) – Orient

+0

如果你是作者,如果'c',你可以让你的生活更容易,如果你从非模板基类'类派生'c' foo {}'然后检查'F'是否使用普通的'std :: is_base_of'从'foo'派生。 –

+1

@ JohannesSchaub-litb是的,我知道,同时我决定使用这样一个'e_tag'类。 – 0xbadf00d

回答

3

这个答案重点在于这个问题;

给定一个类型F,我怎么能检查是否有某种类型的B这样Fc<F, B>衍生?

并且为清晰起见;

这种特点应该检查是否Fc<F, B>推导出一些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_函数的不需要的行内定义。

注:溶液假定/断言可访问的基类(即,不是privateprotected)。如果基类为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'是否来自'c '对于* some *'B'(并且B'是什么并不重要)。 – 0xbadf00d

+0

您应该将其编辑到问题中。就目前而言,问题包含对D和B推导以及类似e的引用,这些看起来并不相关,从而使问题变得模糊不清。 – Niall

+0

我已经在问题中明确表达了,因为我表示治疗应该检查是否存在*某种类型... – 0xbadf00d