Частичная специализация метода в шаблоном классе
Дано:
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
.
Ответы
Ответ 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;
}
};