C++: How is this technique of compile-time polymorphism called and what are the pros and cons?

試著忘記壹切 提交于 2019-12-12 17:02:47

问题


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;
}

which outputs

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.

My questions are:

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

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

    3. How does this relate to CRTP? To me it seems that the same is achieved, with all pros and cons of CRTP.


回答1:


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.

In sum I would say that:

  • It's a win if you utilize the ability to implement something once and write the differences inline with no perf penalty
  • It's a win if you want to be explicit in your design about there being a limited number of implementations.

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.



来源:https://stackoverflow.com/questions/43831896/c-how-is-this-technique-of-compile-time-polymorphism-called-and-what-are-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!