模板专业化不考虑继承层次结构。例如,如果我专门设计一个模板Base
并实例化它Derived
,不会选择专业(参见下面的代码(1))。
这可能是一个主要障碍,因为它有时会导致违反里氏替换原则。例如,在工作时这个问题 https://stackoverflow.com/q/7917853/20984,我注意到我无法使用 Boost.Range 算法std::sub_match
虽然我可以std::pair
. Since sub_match
公开继承自pair
,常识表明我可以用sub_match
到处都是pair
使用,但是由于使用模板专业化的特征类而失败。
我们可以通过使用部分模板专业化以及enable_if
and 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"
}
enable_if
更灵活
我认为你应该更喜欢enable_if方法:它可以实现你可能需要的一切,甚至更多。
例如。可能存在派生类可替换基类的情况,but你[不能假设/不想应用]相同的特征/专业化是有效的(例如,因为 Base 是 POD 类,而 Derived 和非 POD 行为或类似的行为与类组成完全正交)。
enable_if
使您能够准确定义条件。
混合方法
您还可以通过实现一个特征类来实现一些中间立场,该特征类从通用特征派生一些特定于应用程序的特征。 “自定义”特征可以使用enable_if和元编程技术来根据需要以多态方式应用特征。这样,您的实际实现就不必重复一些复杂的enable_if/dispatch舞蹈,而可以简单地使用自定义特征类(隐藏复杂性)。
我认为一些(很多?)Boost 库使用混合方法(我已经看到它以某种方式桥接,例如 fusion/mpl,我认为 Spirit 中还有各种迭代器特征)。
我个人喜欢这种方法,因为它可以有效地将“管道”与图书馆的核心业务隔离开来,从而使维护变得容易和文档(!) 容易多了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)