【问题标题】:Type trait to check whether some type is derived from a class template类型特征以检查某些类型是否派生自类模板
【发布时间】:2016-04-14 20:03:25
【问题描述】:

请考虑以下代码sn-p:

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&lt;F, B&gt;

示例:对于F = e&lt;D&gt;,有一些类型B 取决于D,这样F 派生自c&lt;F, B&gt;

【问题讨论】:

标签: c++ templates c++14 typetraits c++17


【解决方案1】:

这个答案集中在问题上;

给定一个类型F,我如何检查是否存在某种类型B 使得F 派生自c&lt;F, B&gt;

以及为清楚起见的注释;

该特征应该检查 F 是否从 c&lt;F, B&gt; 派生一些 BB 是什么并不重要)。

两个constexpr 函数可用于“吸引”和区分基本c&lt;F, B&gt; 与其他类型。 函数模板受到青睐,因为它们能够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...");
}

【讨论】:

  • 它既不应该是固定的,也不应该是一个论点。这就是问题的全部意义所在。该款待应该检查F 是否源自c&lt;F, B&gt;一些 BB 是什么并不重要)。
  • 您应该将其编辑到问题中。就目前而言,该问题包含对 D 和 B 派生的引用以及似乎不相关的类 e,从而使问题变得模糊。
  • 我已经在问题中明确表示了,因为我说过该款待应该检查是否存在 exists 某种类型...
  • @0xbadf00d :“我已经在问题中明确表示”这当然是主观的。无论如何,你的问题对我来说似乎是一团糟。
  • @Niall Do return {}; 而不是 return true_type;。无需重复!
猜你喜欢
  • 2016-07-22
  • 2014-11-08
  • 2011-08-25
  • 1970-01-01
  • 2018-03-30
  • 1970-01-01
  • 2019-08-27
相关资源
最近更新 更多