c++ - 模板特化不适用于派生类

标签 c++ templates

我正在为我的一个类做模板特化,我遇到了一些意想不到的事情..

这是我的代码:

class Base {};
class Derived : public Base {};

template<typename T>
void doSomething(T t) { cout << "All Types!" << endl; }

template<>
void doSomething(Base b) { cout << "Base!" << endl; }

int main() {
    Derived d;
    doSomething(d);       //prints "All Types!"

    return 0;
}

我有一个模板函数 doSomething(T) 接受任何类型的参数……除了基类类型。

所以我将 doSomething 模板专门用于 Base 类型的参数,所以它做了一些不同的事情。

但是,当我将派生类传递给 doSomething 时,它会打印“All Types!”,而我希望它打印“Base!”,因为派生类本质上也是一个基类。

为什么这个特化不适用于 Derived?

有什么办法让它起作用吗?

谢谢

>>> Test Link <<<


更新:

有人提到重写而不是模板特化..但在这种情况下我该如何重写函数?

如果我有:

template<typename T>
void doSomething(T t) { cout << "All Types!" << endl; }

void doSomething(Base b) { cout << "Base!" << endl; }    

然后 doSomething(d) 也会打印“所有类型!”而不是“Base!”,因为 Derived2 对象将被简单地视为类型模板参数

最佳答案

当你doSomething(Derived)你导致你的templateT=Derived 进行推测性实例化.

这行得通(没有 SFINAE),所以它成为候选者。

doSomething(Base)要么不被考虑,要么比 doSomething(Derived) 更差.

特化只是改变了 doSomething 的那个实例化的实现。 .它根本不会改变人们对它的看法。

覆盖添加另一个覆盖,然后与您的 template 竞争使用通常规则的版本。

我们可以通过几种方式将调用路由到 doSomething通过了 Base或从基派生到单个实现的任何类。我会显示 2。

首先,标签调度。

namespace aux {
  template<class T> void doSomething( std::true_type /* is Base */, T t ) {
    // T is a class derived from Base
  }
  template<class T> void doSomething( std::false_type /* is Base */, T t ) {
    // T is not class derived from Base
  }
}
template<class T> void doSomething( T t ) {
  aux::doSomething( std::is_base_of< Base, T >{}, std::forward<T>(t) );
}

(将 {} 替换为 () ,并在 C++03 中删除 std::forward<T>)

在这里,我们显式路由 Base 的派生类到不同的覆盖。

另一种方法是 SFINAE 排除 template出于考虑,并有一个覆盖:

template<class T>
typename std::enable_if< !std::is_base_of<Base, T>::value >::type
doSomething( T t ) { /* blah */ }

void doSomething( Base b ) { /* foo */ }

现在 template SFINAE 不考虑版本,而是使用覆盖。

我发现标签分发更干净。

关于c++ - 模板特化不适用于派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25064214/

相关文章:

c++ - 使用gdb分析核心转储帧

c++ - CMAKE 为 dylib 创建 OSX 包?

c++ - Qt 中的多选和非多选复选框

ios - 使用复选框自定义 XCode 文件模板

c++ - 编译和评估 conditional_t 中的错误大小写问题

c++ - C++,可以采用ifstream或istringstream的函数

c++ - 将数据从构造函数传递到成员函数

c++ - 为什么可变参数模板的模板特化与非可变模板的特化不同?

django - 包含来自 django 模板的静态文件

javascript - 脚本类型模板包含脚本标签