Частичная специализация метода в шаблоном классе - программирование
Подтвердить что ты не робот

Частичная специализация метода в шаблоном классе

Дано:

struct A
{
    virtual bool what() = 0;
};

template<typename T, typename Q>
struct B : public A
{
    virtual bool what();
};

Я хочу частично специализировать what как:

template<typename T, typename Q>
bool B<T, Q>::what()
{
    return true;
}

template<typename Q>
bool B<float, Q>::what()
{
    return false;
}

Но похоже, что это невозможно (это в С++ 11?), поэтому я попробовал SFINAE:

template<typename T>
typename std::enable_if<std::is_same<T, float>::value, bool>::type B<T>::what()
{
    return true;
}

template<typename T>
typename std::enable_if<!std::is_same<T, float>::value, bool>::type B<T>::what()
{
    return false;
}

Это тоже не работает, я понятия не имею, почему, хотя, кто-нибудь? Итак, я нашел эту тему и в итоге:

template<typename T, typename Q>
struct B : public A
{
    virtual bool what()
    {
        return whatimpl(std::is_same<T, float>());
    }

    bool whatimpl(std::false_type)
    {
        return false;
    }

    bool whatimpl(std::true_type)
    {
        return true;
    }
};

Это окончательное решение работает, но почему технология enable_if не работает? Я также очень открыт для предложений о более чистом ответе, который я еще не встречал.

Я максимально упростил свои примеры - в моем реальном случае использования what() не называется тем, что и на самом деле выполняет справедливую работу, и я хочу "специализироваться" на пользовательском типе, а не float.

4b9b3361

Ответ 1

Частичная специализация явно разрешена стандартом только для шаблонов классов (см. 14.5.5. Частичные специализации шаблона шаблона)

Для членов шаблона класса допускается только явная специализация.

14.7 (3) говорит:

Явная специализация может быть объявлена ​​для шаблона функции, шаблона класса, члена класса шаблон или шаблон участника. Явное объявление специализации вводится template < > .

Итак, любое определение, начинающееся с

template<typename T>  

не является разрешенным синтаксисом для члена специализации шаблона класса.

[править]

Что касается попытки SFINAE, это не сработало, потому что на самом деле здесь нет ни перегрузок, ни специализаций (SFINAE работает при определении набора функций-кандидатов для разрешения перегрузки или при выборе соответствующей специализации). what() объявлен как один метод шаблона класса и должен иметь одно определение, и это определение должно иметь форму:

template<typename T, typename Q> 
B<T,Q>:: bool what(){...}

или может быть также явно специализирован для конкретного экземпляра класса B:

template<> 
B<SomeParticularTypeT,SomeParticularTypeTypeQ>:: bool what(){...}

Любые другие формы синтаксически недействительны, поэтому SFINAE не может помочь.

Ответ 2

Почему бы просто не изменить его на..

template<typename T, typename Q> 
struct B : public A 
{   
   bool what()
   {
      return false; //Or whatever the default is...
   }
}; 

template<typename Q>
struct B<float, Q> : public A 
{   
   bool what()
   {
      return true;
   }
};