选择专用于派生实例的基类的类模板



请考虑以下示例程序:

#include <iostream>
template<typename T>
struct Dispatch
{
static void send(T&) { std::cout << "unknownn"; }
};
struct Processor
{
template<typename T>
void process(T&& t) { Dispatch<T>::send(t); }
};
template<typename T>
struct Base
{};
template<typename T>
struct Dispatch<Base<T>>
{
static void send(Base<T>&) { std::cout << "basen"; }
};
struct Deriv : Base<int>
{};
int main()
{
Processor p;
p.process(Base<int>{}); // prints "base"
p.process(Deriv{});     // prints "unknown"
return 0;
}

当使用Deriv实例(这是一个Base子类(调用Processor::process()时,我希望选择专门用于Base类模板的Dispatcher()

但是,在上面的示例中,将发生以下情况:

  • Base<T>实例传递给process()调用Base<T>专用化
  • Deriv实例传递给主类模板process()调用主类模板

问题:

  • 为什么Base<T>不是比主要类模板更好的Deriv专业化?
  • 当传递Base<T>子类时,是否有一种通用方法可以将Base<T>专用化称为专业化?

使用 SFINAE,您可以执行以下操作:

// Traits to detect inheritance:
template <typename T> std::true_type derive_from_base_impl(Base<T>*);
std::false_type derive_from_base_impl(...);
template <typename T>
using derive_from_base_t = decltype(derive_from_base_impl(std::declval<T*>()));

然后一些变化

template<typename T, typename Enabler = void>
struct Dispatch
{
static void send(T&) { std::cout << "unknownn"; }
};
template<typename T>
struct Dispatch<T, std::enable_if_t<derive_from_base_t<T>::value>>
{
static void send(T&) { std::cout << "basen"; }
};

演示

模板专用化适用于字面上相同的类型。如果您专门用于Base模板,则此专用化将不适用于Derived

解决此问题的一种方法是使用部分专用化,您可以为派生自Base的类型启用该专用化。

最新更新