我有两个模板类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";
}
我想我可以将S1
和S2
作为模板参数添加到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>()));
};
答案 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
会产生结果类型。
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
以获得一些额外的好处。