Overriding a virtual method in a base class with conditional type traits in derived template class
谁能解释为什么下面的代码给出了错误"错误C2259:‘PrimTyValue'":不能在VisualStudio 2015 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 39 40 41 42 | #include <type_traits> #include <typeinfo> class BasePropertyValue { public: virtual int ConvertToDevice(void** ptrdObject) = 0; }; template<typename T> class PropertyValue : public BasePropertyValue { public: T value; PropertyValue(T val) { value = val; } template<class Q = T> typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject) { return 1; } template<class Q = T> typename std::enable_if<std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject) { return 2; } }; void main() { PropertyValue<double>* prop1 = new PropertyValue<double>(20); prop1->ConvertToDevice(nullptr); double x = 20; PropertyValue<double*>* prop2 = new PropertyValue<double*>(&x); prop2->ConvertToDevice(nullptr); return; } |
[编辑]这不是重复的问题,因为条件特征方面。
首先,将要重写的函数声明为模板。不能有模板虚拟函数。就这么简单。
对于解决方案,您似乎已经使这些模板能够在两个实现之间切换。一个简单的解决方案是实现一个重写的函数,然后调用其中的模板函数:
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 | template<typename T> struct PropertyValue : BasePropertyValue { T value; // simpler constructor PropertyValue(T val) : value{std::move(val)} {} // the override keyword is important int ConvertToDevice(void** ptrdObject) override { return ConvertToDeviceImpl(ptrdobject); } private: template<class Q = T> typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDeviceImpl(void** ptrdObject) { return 1; } template<class Q = T> typename std::enable_if<std::is_pointer<Q>::value, int>::type ConvertToDeviceImpl(void** ptrdObject) { return 2; } }; |
问题是
1 2 3 4 5 | template<class Q = T> typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject) { return 1; } |
是与基类中的纯虚拟方法不匹配(且不重写)的模板方法。
其他启用了sfinae的函数也有同样的问题。
因此,
一种可能的解决方案是创建一个中间基类,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class BasePropertyValue { public: virtual int ConvertToDevice (void ** ptrdObject) = 0; }; template <typename T, bool = std::is_pointer<T>::value> class midClass; template <typename T> class midClass<T, false> : public BasePropertyValue { public: int ConvertToDevice (void ** ptrdObject) override { return 1; } }; template <typename T> class midClass<T, true> : public BasePropertyValue { public: int ConvertToDevice (void ** ptrdObject) override { return 2; } }; template <typename T> class PropertyValue : public midClass<T> { public: T value; PropertyValue (T val) { value = val; } }; |