c++ - 在派生模板类中使用条件类型特征覆盖基类中的虚拟方法

标签 c++ c++11 templates sfinae typetraits

谁能解释为什么下面的代码在 Visual Studio 2015 C++ 中给出错误“error C2259: 'PropertyValue': cannot instantiate abstract class”?

编译器是否无法识别派生类 PropertyValue 中的条件指定函数 ConvertToDevice() 具有相同的签名?

非常感谢,

约翰

#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;
}

[edit] 由于条件特征方面的原因,这不是一个重复的问题。

最佳答案

首先,您将要覆盖的函数声明为模板。你不能有模板虚函数。就这么简单。

对于解决方案,您制作这些模板似乎只是为了能够在两种实现之间切换。一个简单的解决方案是实现一个覆盖的单个函数,然后在其中调用一个模板函数:

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;
    }
};

关于c++ - 在派生模板类中使用条件类型特征覆盖基类中的虚拟方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46163972/

相关文章:

c++ - 编译器可以报告未知属性的错误吗?即使有范围?

c++ - 如何正确增加 C++11 std::atomic?

c++ - 如何强制SFINAE选择第二个结构定义?

c++ - 模板类的构造函数在使用 new 关键字时调用类型构造函数

c++ - 如何打印 Trie 中的所有单词?

C++:调试 C++ 模板链接器错误

c++ - 如何使用 boost lib 编译 c++ 代码?在 Ubuntu 上

c++ - std::regex 在 VC2015U3 上比 boost::regex 慢得多

c++ - 无法编译代码,因为它在 C++11 中已弃用

c++ - 这似乎是 C++ Primer 5th edition 一书中的错误