【发布时间】:2011-12-17 06:00:50
【问题描述】:
模板特化不考虑继承层次结构。例如,如果我为Base 特化一个模板并用Derived 实例化它,则不会选择特化(参见下面的代码(1))。
这可能是一个主要障碍,因为它有时会导致违反 Liskov 替换原则。例如,在处理this question 时,我注意到我不能将Boost.Range 算法与std::sub_match 一起使用,而我可以与std::pair 一起使用。由于sub_match 公开继承自pair,因此常识表明我可以在使用pair 的任何地方替换sub_match,但这会由于使用模板专业化的特征类而失败。
我们可以通过使用部分模板专业化以及enable_if 和is_base_of 来克服这个问题(参见代码(2))。我是否应该始终支持这种解决方案而不是完全专业化,尤其是在编写库代码时?我监督过的这种方法有什么缺点吗?您是否经常使用或经常看到这种做法?
示例代码
(1)
#include <iostream>
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<Derived>::f(); // prints "Default"
}
(2)
#include <type_traits>
#include <iostream>
struct Base {};
struct Derived : public Base {};
template <typename T, typename Enable = void>
struct Foo
{
static void f() { std::cout << "Default" << std::endl; }
};
template <typename T>
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<Derived>::f(); // prints "Base"
}
【问题讨论】:
-
+1 很好的问题和动机。
-
+1。确实是一个很好的问题。
标签: c++ templates template-specialization typetraits