繁体   English   中英

指定类的基类的C ++模板参数的用途和缺点?

[英]Uses and drawbacks of C++ template parameters specifying a class' base classes?

背景

最近我一直在考虑如何设计一个特定的软件,有一点我已经制作了下面这篇文章:

template <typename ... Mixins>
class Foo : public virtual Mixins... {
    /* ... */
};

我的想法是能够根据用户的需要使用其他属性或行为来扩充基类。 假设一个应用程序需要使用带有标识号的Foo 也许其他一些应用程序需要能够用颜色来谈论Foo 可以通过添加以下类来满足这些需求:

class HasID {
    int m_id = -1;

public:
    int getID() { return m_id; }
    void assignID(int id) { m_id = id; }
};

class HasColor {
public:
    int color = 0;
};

问题

我对这段代码的两个问题如下:

  1. 使用这样的模板有什么用途和缺点?
  2. 这种特殊模式有名字吗?

附加示例代码

这是另一个示例,展示了可以打印扩充类对象的详细信息。

打印功能:

// Default printBase
template <typename Base>
void printBase(std::ostream& out, Base& x) {}

// printBase for HasID
template <>
void printBase(std::ostream& out, HasID& x) {
    out << ", ID=" << x.getID();
}

// printBase for HasColor
template <>
void printBase(std::ostream& out, HasColor& x) {
    out << ", color=" << x.color;
}

// Recursive step of printBases
template <typename Derived, typename Base, typename ... Bases>
void printBases(std::ostream& out, Derived& x, Base& y) {
    printBase(out, y);
    printBases<Derived, Bases...>(out, x, x);
}

// Base case of printBases    
template <typename Derived>
void printBases(std::ostream& out, Derived& x, Derived& y) {}

// ostream operator
template <typename ... Mixins>
std::ostream& operator<<(std::ostream& out, Foo<Mixins...>& x) {
    out << "<Foo";
    printBases<Foo<Mixins...>, Mixins...>(out, x, x);
    return out << '>';
}

主要:

int main()
{
    Foo<> plainFoo;
    Foo<HasID> fooWithID;
    fooWithID.assignID(42);
    Foo<HasID, HasColor> multiTalentedFoo;
    multiTalentedFoo.assignID(1234);
    multiTalentedFoo.color = 0xff0000;

    std::cout
        << plainFoo << '\n'
        << fooWithID << '\n'
        << multiTalentedFoo << '\n';
}

输出:

<Foo>
<Foo, ID=42>
<Foo, ID=1234, color=16711680>

我对这段代码的两个问题如下:

这种特殊模式有名字吗?

使用这样的模板有什么用途和缺点?

CRTP“奇怪地反复出现模板模式”或有时也称为“mixin”。

https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

我们真的想再次讨论这里的缺点,而网络知道这种模式/成语吗? 讨论得足够多了:-)

https://softwareengineering.stackexchange.com/questions/123886/is-crtp-used-much-and-why-it-is-isnt

本文http://www.drdobbs.com/building-more-flexible-types-with-mixins/184402056说明:

CRTP技术的最大缺点是构造函数不是继承的。 这意味着如果在实现类中使用初始化构造函数,则每个扩展都必须具有适当的初始化构造函数。 这导致扩展受到更多限制,因此不太有用。

这不再是真的,因为对于c ++ 14,你很有可能使用可变参数模板和基类的构造函数调用链来终止该参数。 继承和委托构造函数也有助于实现此目的。

与所有模板一样,您必须记住每个实例化都是一种新类型,可能会导致可执行文件中出现大量代码重复。 我经常使用这种模式并接受成本。 另一种方法是手工编写可执行大小不小的代码。 你必须为你需要付出代价。

让我回答第二部分:是的,这个模式有一个名字: Static Polymorphism

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM