检查实现了哪些基类

时间:2018-04-29 12:34:06

标签: c++ templates inheritance

我有两个模板类A和B

template <typename T> class A { /* ... */ };
template <typename T> class B { /* ... */ };

现在我想编写一个执行不同操作的函数,具体取决于在传递的参数中实现的基类。

template <typename T>
void foo(const T& object) {
  if ( /* T inherits from some A<S1> */ )
    std::cout << "object has type A";
  if ( /* T inherits from some B<S2> */ )
    std::cout << "object has type B";
}

我想我可以将S1S2作为模板参数添加到foo,但为每次调用手动指定它们是一件非常麻烦的事。理论上,如果T已知,编译器应该能够检查它是否继承A<S>

可以这样做吗?

编辑:

除了StoryTeller的解决方案之外,我正在使用这段代码来相应地投射我的T - 对象:

template<template<typename...> class TT, class T>
struct specialization_base_of {

    template<typename... Args>
    static constexpr TT<Args...>  checkVal(TT<Args...> const&);

    static constexpr void checkVal(...);

    template<typename... Args>
    static constexpr TT<Args...>&  checkRef(TT<Args...> const&);

    static constexpr void checkRef(...);

    template<typename... Args>
    static constexpr TT<Args...> const& checkCref(TT<Args...> const&);

    static constexpr void checkCref(...);

    template<typename... Args>
    static constexpr TT<Args...>*  checkPtr(TT<Args...> const&);

    static constexpr void checkPtr(...);

    using value_type = decltype(checkVal(std::declval<T>()));
    using ref_type = decltype(checkRef(std::declval<T>()));
    using cref_type = decltype(checkCref(std::declval<T>()));
    using ptr_type = decltype(checkPtr(std::declval<T>()));
};

1 个答案:

答案 0 :(得分:3)

依赖于重载解析的好老技巧也应该在这里工作:

template<template<typename...> class TT, class T>
struct is_specialization_base_of {
    template<typename... Args>
    static constexpr std::true_type  check(TT<Args...> const&);

    static constexpr std::false_type check(...);

    static constexpr bool value = decltype(check(std::declval<T>()))::value;
};

第一个模板参数是模板名称,它可以接受任意数量的类型参数。你需要一个,但为什么限制自己?

然后我们定义了两个重载,一个是接受TT的任何假设特化的模板,第二个是一个C风格的变量参数函数的回退。这就是整个机器。如果我们使用任何公开来自check假设专业的类调用TT,则会由于重载解析的工作方式而选择第一个重载。否则选择后备。

我们的特征的价值取决于decltype未评估的上下文中产生的类型,在那里执行了重载决策,但由于它是一个未评估的上下文,因此无需定义,只需声明。因此decltype会产生结果类型。

Here's a simple test suite

struct C1 : A<int> {};
struct C2 : B<int> {};

struct C3 : A<int>, B<char> {};

static_assert(is_specialization_base_of<A, C1>::value);
static_assert(!is_specialization_base_of<B, C1>::value);

static_assert(!is_specialization_base_of<A, C2>::value);
static_assert(is_specialization_base_of<B, C2>::value);

static_assert(is_specialization_base_of<A, C3>::value);
static_assert(is_specialization_base_of<B, C3>::value);

我将把这个特性插入你的模板功能中。我建议您将if转换为if constexpr以获得一些额外的好处。