Специализация шаблона не принимает во внимание иерархию наследования. Например, если я специализирую шаблон для База
и его экземпляр с помощью Производный
, специализация не будет выбрана (см. Код (1) ниже).
Это может быть серьезным препятствием, поскольку иногда приводит к нарушению принцип подстановки Лискова. Например, работая над этим вопросом , я заметил, что не могу использовать алгоритмы Boost.Range с std :: sub_match
, тогда как я мог бы с std :: pair
. Поскольку sub_match
публично наследуется от пары
, здравый смысл подсказывает, что я мог бы везде заменить sub_match
парой
], но это не удается из-за классов признаков, использующих специализацию шаблонов.
Мы можем преодолеть эту возникает при использовании частичной специализации шаблона вместе с enable_if
и is_base_of
(см. код (2)).Должен ли я всегда отдавать предпочтение этому решению, а не полной специализации, особенно при написании кода библиотеки? Есть ли у этого подхода недостатки, которые я заметил? Вы используете эту практику или часто видели?
Примеры кодов
(1)
#include
struct Base {};
struct Derived : public Base {};
template < typename T >
struct Foo
{
static void f() { std::cout << "Default" << std::endl; }
};
template <>
struct Foo< Base >
{
static void f() { std::cout << "Base" << std::endl; }
};
int main()
{
Foo::f(); // prints "Default"
}
(2)
#include
#include
struct Base {};
struct Derived : public Base {};
template
struct Foo
{
static void f() { std::cout << "Default" << std::endl; }
};
template
struct Foo<
T, typename
std::enable_if< std::is_base_of< Base, T >::value >::type
>
{
static void f() { std::cout << "Base" << std::endl; }
};
int main()
{
Foo::f(); // prints "Base"
}