Вот как на самом деле может работать SFINAE с частичной специализацией:
template<typename T, typename Sfinae = void>
struct Foo {
/* catch-all primary template */
/* or e.g. leave undefined if you don't need it */
};
template<typename T>
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
/* matches types derived from BasePolicy */
Foo();
};
Определение этого конструктора может быть неловко введено с помощью:
template<typename T>
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
{
/* Phew, we're there */
}
Если ваш компилятор поддерживает псевдонимы шаблона (это особенность C ++ 11), в которой вы можете сократить многословность:
template<typename T>
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;
// Somewhat nicer:
template<typename T>
struct Foo<T, EnableIfPolicy<T>> {
Foo();
};
template<typename T>
Foo<T, EnableIfPolicy<T>>::Foo() {}
Примечание: ваш исходный ответ относится к утилитам Boost, таким как boost::enable_if_c
и boost::is_base_of
.Если вы используете это вместо std::enable_if
и std::is_base_of
(которые из C ++ 11), тогда использование выглядит как
typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type
, что дает преимущество в избавлении от одного ::value
.