如何在C ++中强制使用奇怪的重复模板模式

时间:2015-05-14 07:45:28

标签: c++ templates inheritance crtp

我有以下基本模板类。

template<typename T>
class Base {
  public:
    void do_something() {
    }
};

它旨在用作奇怪的重复模板模式。它应该像class B : public Base<B>一样继承。它必须继承,如class B : public Base<SomeoneElse>。我想静态地执行这个要求。如果有人使用了这个错误,我预计编译阶段会出错。

我正在做的是在static_cast<T const&>(*this)中添加do_something()。这样,继承模板的类是继承自作为模板参数提供的类。抱歉这个令人困惑的表情。简单地说,B需要SomeoneElseclass B : public Base<SomeoneElse>中的B继承。

我不知道这是否是实现这一目标的最佳方式。看起来很粗鲁。

但是我想做更多。我想确保SomeoneElse本身INFO [94db8027] Running /usr/bin/env uptime on leehambley@example.com:22 DEBUG [94db8027] Command: /usr/bin/env uptime DEBUG [94db8027] 17:11:17 up 50 days, 22:31, 1 user, load average: 0.02, 0.02, 0.05 INFO [94db8027] Finished in 0.435 seconds command successful. 。我怎么能这样做?

3 个答案:

答案 0 :(得分:8)

Base的构造函数(或析构函数)设为private,然后将T设为friend。这样,构建/破坏Base<T>的唯一方法就是T

答案 1 :(得分:3)

如果您的类包含一些代码:

T* pT = 0;
Base *pB = pT;

如果TBase不分配兼容,则会出现编译错误。

这种检查在C ++ 11中已经形式化,因此您不必手动编写它并且可以获得有用的错误消息:

#include <type_traits>

template<typename T>
class Base {

public:
    void do_something() 
    {
        static_assert(
            std::is_base_of<Base, T>::value,
            "T must be derived from Base");
    }
};

class B : public Base<B> { };

int main()
{
    B b;
    b.do_something();
}

至于确保Base的类型参数正是从它派生的类,这看起来在概念上是有缺陷的。充当基类的类不能“谈论”继承它的类型。它可以通过多重继承而不是一次继承,或者根本不继承。

答案 2 :(得分:1)

到目前为止有两个好的答案。这是另一个使用为某些方法生成自定义访问键的习语(在这种情况下是构造函数)。它提供了正确使用的绝对保证,同时不将基础中的私有方法暴露给派生。

它还可以用于根据具体情况控制对基类中其他方法的访问。

template<class Derived>
struct Base
{
private:
    // make constructor private
    Base() = default;
protected:
    // This key is protected - so visible only to derived classes
    class creation_key{
        // declare as friend to the derived class
        friend Derived;
        // make constructor private - only the Derived may create a key
        creation_key() = default;
    };

    // allow derived class to construct me with a key
    Base(creation_key)
    {}

    // other methods available to the derived class go here

private:
    // the rest of this class is private, even to the derived class
    // (good encapsulation)
};

struct D1 : Base<D1>
{
    // provide the key
    D1()
    : Base<D1>(creation_key())
    {}

};
相关问题