C++:如何调用这种编译时多态技术,其优缺点是什么? [英] C++: How is this technique of compile-time polymorphism called and what are the pros and cons?

查看:39
本文介绍了C++:如何调用这种编译时多态技术,其优缺点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在工作中,我遇到过基本上如下所示的代码:

At work, I have come across code which basically looks like that:

#include <iostream>

using namespace std;

enum e_Specialization {
    Specialization_A,
    Specialization_B
};

template<e_Specialization>
class TemplatedBase {
public:
    string foo() { return "TemplatedBase::foo"; }
};

template<>
string TemplatedBase<Specialization_A>::foo() { return "TemplatedBase<Specialization_A>:foo"; }

int main() {
    TemplatedBase<Specialization_A> o;
    cout << o.foo() << endl;
    return 0;
}

哪个输出

TemplatedBase<Specialization_A>:foo

我在任何地方都找不到关于此技术的任何讨论.

I haven't been able to find any discussion on this technique anywhere.

代码的创建者主要从事物的优化方面争论,没有发生虚拟调度.在我们的例子中,这种优化不是必需的,但我知道它是如何有用的.

The code's creator argued mostly from the optimization side of things, that no virtual dispatch happens. In our case this optimization is not necessary, but I see how it could be useful.

我的问题是:

  1. 这种技术是否有记录在案,有名字吗?

  1. Is this technique documented anywhere and does it have a name?

与继承特化相比,这有什么优势吗?

In comparison to specialization by inheritance, are there any advantages to this at all?

3.这与 CRTP 有何关系?在我看来,CRTP 的所有优点和缺点都可以实现相同的效果.

推荐答案

至于该技术是否被记录(如果您使用 C++11 或更高版本执行此操作,请使用枚举类),这是一个公平的在枚举或布尔值上进行模板化,然后进行专业化的常用技术.

As far as whether the technique is documented (and if you are doing this with C++11 or later, please use an enum class), it's a fairly common technique to template on an enum or a boolean and then do your specializations.

一个明显的区别是,使用这种技术,您显然无法在不修改主要代码的情况下添加更多专业化.枚举(或枚举类)只有这么多值.这可能是好事也可能是坏事,这取决于您是否希望对其进行集中跟踪.但这可以通过对类进行模板化并对其进行封装来轻松改变,这是第三种选择,它不完全是这种技术,也不涉及公共继承.

One clear difference is that with this technique, you obviously can't add more specializations without modifying the primary code. An enum (or enum class) only has so many values. That could be either a good or bad thing, depending on whether you want it to be centrally tracked. But that could easily be changed by templating on a class and encapsulating it, a third option which isn't quite this technique nor does it involve public inheritance.

恕我直言,这种技术的最大优势在于您可以选择内联实现.例如:

This technique has its biggest advantage, IMHO, in that you have the option to implement things inline. For example:

template<e_Specialization e>
class TemplatedBase {
public:
    void bar() {
        // code
        if (e == Specialization_A) {
        ...
        }
        // code
    }
};

对于从一开始就知道处于性能关键路径中的类,我经常看到这种情况.可能有一个布尔变量来控制是否发生侵入性性能分析.因为这些分支在编译时是已知的,所以它们被简单地优化.这是一个很好的方法,因为您仍然可以在同一个构建中使用该类的两个版本(例如,在两个版本上运行单元测试).

I see this a lot with classes that are known from the outset to be in a performance critical path. There could be a boolean variable that controls whether or not intrusive performance profiling occurs. Because these branches are known at compile time, they are trivially optimized. This is a good way to do it because you can still use both versions of the class in the same build (e.g. run unit tests on both).

与继承相比的另一个区别是,派生类可以根据需要轻松添加状态.这种技术目前需要专门化整个类来添加状态.同样,这可能是好是坏.如果您不需要打破这些限制,则更受限制的设计是好的.您可以轻松更改设计以启用添加额外状态:

Another difference compared to inheritance, is that derived classes can easily add state if they need to. This technique as it stands would require specializing the whole class to add state. Again, this could be good or bad; a more constrained design is good if you don't need to break those constraints. And you can easily change the design to enable adding extra state:

template <e_Specialization e>
struct ExtraState {};

template <e_Specialization e>
class TemplatedBase : private ExtraState<e> {
...

第三个小例子是,您没有公开任何继承关系.这通常很小,但请记住,您可以获得切片甚至隐式引用/指针转换之类的东西.这是这项技术的一个非常严格的胜利.

A third, minor example, is that you aren't exposing any inheritance relationship. This is mostly small, but remember that you can get things like slicing or even implicit reference/pointer conversion. This is a pretty strict win for this technique.

总而言之,我会说:

  • 如果您能够利用一次实现某事的能力并在没有性能损失的情况下内联写入差异,那将是一场胜利
  • 如果您想在设计中明确说明实现数量有限,这将是一个胜利.

如果这两个都不对,那么与仅使用继承相比,设计有点不正统,也有点复杂,尽管它实际上并没有任何强大的技术劣势.因此,如果您周围有大量初级开发人员,则此代码可能更难阅读.

If neither of those are true then the design is a bit unorthodox and a little more complex compared to just using inheritance, although it doesn't really have any strong technical disadvantage. So if you have a good number of junior devs around, this code might be harder to read.

这篇关于C++:如何调用这种编译时多态技术,其优缺点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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