簡體   English   中英

在派生模板類中使用條件類型特征覆蓋基類中的虛擬方法

[英]Overriding a virtual method in a base class with conditional type traits in derived template class

誰能解釋為什么下面的代碼在Visual Studio 2015 C ++中給出錯誤“錯誤C2259:'PropertyValue':無法實例化抽象類”?

編譯器是否無法識別派生類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;
    }
};

問題是

template<class Q = T>
typename std::enable_if<!std::is_pointer<Q>::value, int>::type ConvertToDevice(void** ptrdObject)
{
    return 1;
}

是與基類中的純虛擬方法不匹配(也不覆蓋)的模板方法。

其他啟用SFINAE的功能也存在相同問題。

因此PropertyValue仍然是純虛擬類,無法實例化。

一種可能的解決方案是創建一個中間基類,如下所示的midClass

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM