Специализация шаблона enable_if - PullRequest
5 голосов
/ 21 мая 2019

Я пытаюсь специализировать шаблон следующим образом:

class PropertyBase
{
public:
    SfPropertyBase(string name)
    {
        Name = name;
    }

    virtual ~SfPropertyBase() {}

    string Name;

    virtual bool FromString(Object* obj, string str) = 0;

};


template< typename T>
class Property : public SfPropertyBase
{
public:
    Property(string name) : SfPropertyBase(name)
    {
        //specific to Property stuff
    }



    template<typename U = T>
    typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value), bool>::type
    FromString(Object* obj, string str)
    {
        //do something
        return true;
    }

    template<typename U = T>
    typename std::enable_if<!std::is_class<U>::value || !std::is_pointer<U>::value), bool>::type
    FromString(Object* obj, string str)
    {
        //do something
        return true;
    }
}

Затем, когда я пытаюсь инициализировать экземпляр этого класса:

 auto prop = new Property<int>("IntProperty");

Я получаю invalid new-expression of abstract class type Property<int>. Я понимаю, что в PropertyBase есть абстрактная функция, но я также предоставляю обе специализации для Property, где T - это класс, а где - нет.

Что происходит и как это исправить?

Примечание: я хочу добиться специализации FromString, если T - это класс / указатель, и все другие случаи.

Ответы [ 2 ]

5 голосов
/ 21 мая 2019

Обе FromString в Property являются шаблонами функций, они не могут переопределить не шаблонную virtual функцию базового класса. (Фактически шаблоны функций не могут быть virtual functions ).

Вы можете добавить еще один не шаблон FromString в Property; и вы можете обеспечить переопределение, используя ключевое слово orverride. например, * 1 016 *

bool FromString(Object* obj, string str) override {
    return FromString<>(obj, str);
}

ЖИТЬ

4 голосов
/ 21 мая 2019

Шаблон функции не может использоваться в качестве переопределения для не шаблонной виртуальной функции.Шаблон функции - это не функция, это рецепт создания функций по требованию при вызове.

Код должен будет вызывать FromString для вашего объекта производного класса непосредственно для SFINAEработать.Если вы хотите предоставить другое переопределение, основанное на типе параметра шаблона, один из подходов заключается в переходе через промежуточную базу.

template<typename T, typename = void>
struct FromStringProvider;

template<typename T>
struct FromStringProvider<T, typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value)>::type> : SfPropertyBase {
    bool FromString(Object* obj, string str) override
    {
        //do something
        return true;
    }
};

Если вам нужен доступ к производному классу, тогда подход на основе CRTP может бытьиспользуемый.Просто передайте производный класс в качестве дополнительного параметра и используйте его статический интерфейс для доступа к нужным вам частям.

Этот альтернативный подход особенно полезен, если у вас есть наборы виртуальных функций, все в одинаковых условиях.

...