Templates and inheritance, how to call base virtual method
我的C++框架有一个类层次结构。还有一个通用集合类用于处理对象集(如打印它们)。这是我简化的课堂设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include<iostream> #include<vector> using namespace std; class Base { public: virtual void print() const {cout <<"B" << endl;} }; class Derived : public Base { int x; public: Derived(int _x) : x(_x) {} virtual void print() const {cout <<"D" << x << endl;} }; inline void print_elem(const int e) { cout << e << endl; } inline void print_elem(const Base& e) { e.print(); } template<class T> class Collection { private: vector<T> elems; public: void add(const T& v) { elems.push_back(v); } void print() { for (unsigned i=0; i < elems.size(); ++i) print_elem(elems[i]); } }; int main(int argc, const char *argv[]) { Collection<int> c1; c1.add(2); c1.add(5); c1.print(); Collection<Derived> c2; c2.add(Derived(2)); c2.add(Derived(5)); c2.print(); } |
以上代码编译正常。问题是关于
1 2 3 | inline void print_elem(const Base& e) { e.print(); } template<class T> inline void print_elem(const T& e) { cout << e << endl; } |
为基类和所有派生类以及所有其他类型指定实现时,应使用
template argument deduction/substitution failed:
cannot convert ‘e’ (type ‘const Derived’) to type ‘const unsigned >
char*’
inline void print_elem(const T& e) { cout << e << endl; }
编译器是否可能将
斯芬娜去营救!
如果参数继承自
1 2 3 4 | inline void print_elem(const Base& e) { e.print(); } template<class T, class = std::enable_if_t<!std::is_base_of_v<Base, T> > > inline void print_elem(const T& e) { cout << e << endl; } |
你可以在这里看到一个活生生的例子
我用C++来解决C++ 11,灵感来自于@ AMC176的答案。感兴趣的代码片段将是:
1 2 3 4 | inline void print_elem(const Base& e) { e.print(); } template<class T, class enable_if<!is_base_of<Base,T>::value,Base>::type* = nullptr> inline void print_elem(const T& e) { cout << e << endl; } |