关于模板专业化和继承的良好实践 [英] Good practices regarding template specialization and inheritance

查看:171
本文介绍了关于模板专业化和继承的良好实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

模板特化不考虑继承层次结构。例如,如果我专门为 Base 创建一个模板,并用 Derived 实例化它,则不会选择专业化

Template specialization does not take into account inheritance hierarchy. For example, if I specialize a template for Base and instantiate it with Derived, the specialization will not be chosen (see code (1) below).

这可能是一个主要的障碍,因为它有时会导致违反Liskov替代原则。例如,在处理此问题时,我注意到我无法使用Boost.Range算法与 std :: sub_match ,而我可以用 std :: pair 。由于 sub_match pair 公开继承,常识会指示我可以用 sub_match 到处使用,但是由于trait类使用模板专门化而失败。

This can be a major hindrance, because it sometimes lead to violation of the Liskov substitution principle. For instance, while working on this question, I noticed that I could not use Boost.Range algorithms with std::sub_match while I could with std::pair. Since sub_match inherits publicly from pair, common sense would dictate that I could substitute a sub_match everywhere a pair is used, but this fails due to trait classes using template specialization.

我们可以通过使用部分模板专门化以及 enable_if is_base_of (见代码(2))来克服这个问题。我应该总是喜欢这个解决方案完全专业化,特别是当编写库代码?这种方法有什么缺点,我已经监督?

We can overcome this issue by using partial template specialization along with enable_if and is_base_of (see code (2)). Should I always favor this solution over full specialization, especially when writing library code? Are there any drawbacks to this approach that I have overseen? Is it a practice that you use or have seen used often?

示例代码

(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方法:它启用了你可能需要的一切,更多。

enable_if is more flexible

I think you should really prefer the enable_if approach: it enables everything that you could require and more.

例如可能有这样的情况:派生类是基于Liskov可替代的, 你不能假设/不想应用相同的traits / specializations是有效的(例如因为Base是POD类,而Derived和非POD行为或类似与类构成完全正交的行为)。

E.g. there might be cases where a Derived class is Liskov-Subsitutable for a Base, but you [cannot assume/donot want to apply] the same traits/specializations to be valid (e.g. because the Base is POD class, whereas Derived ands non-POD behaviour or somehting like that that is completely orthogonal to class composition).

enable_if 让你有能力准确地定义条件。

enable_if gives you the power to define exactly the conditions.

您还可以通过实现一个traits类来实现一些中间体,从通用特性。 '自定义'traits可以使用enable_if和元编程技术来应用traits作为你想要的多态。这样,你的实际实现不必重复一些复杂的enable_if / dispatch dance,而是可以简单地使用custom-traits类(隐藏复杂性)。

You could also achieve some middleground by implementing a traits class that derives some application-specific traits from general-purpose traits. The 'custom' traits could use the enable_if and meta-programming techniques to apply traits as polymorphically as you desire. That way, your actual implementations do not have to repeat some complicated enable_if/dispatch dance but instead can simply consume the custom-traits class (that hides the complexity).

我认为一些(许多?)Boost库使用混合方法(我已经看到它在一些容量,它桥梁如fusion / mpl,我认为也各种迭代器

I think some (many?) Boost libraries use the hybrid approach (I've seen it in some capacity where it bridges e.g. fusion/mpl, I think also various iterator traits in Spirit).

我个人喜欢这种方法,因为它可以有效地将'plumbing'与库的核心业务隔离开来,使维护和文档(!)很容易。

I personally like this approach because it can effectively isolate the 'plumbing' from the core-business of a library, making maintenance and documentation (!) a lot easier.

这篇关于关于模板专业化和继承的良好实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆