简体   繁体   English

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

[英]How to force use of curiously recurring template pattern in C++

I have the following base template class. 我有以下基本模板类。

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

It is intended to be used as a curiously recurring template pattern . 它旨在用作奇怪的重复模板模式 It should be inherited like class B : public Base<B> . 它应该像class B : public Base<B>一样继承class B : public Base<B> It must not be inherited like class B : public Base<SomeoneElse> . 不能class B : public Base<SomeoneElse>一样继承class B : public Base<SomeoneElse> I want to statically enforce this requirement. 我想静态地执行这个要求。 If someone uses this wrong, I expect an error in the compiling phase. 如果有人使用了这个错误,我预计编译阶段会出错。

What I'm doing is putting a static_cast<T const&>(*this) in do_something() . 我正在做的是在do_something()放置一个static_cast<T const&>(*this) do_something() This way the class inheriting the template is or inherits from the class provided as the template parameter. 这样,继承模板的类是继承自作为模板参数提供的类。 Sorry for the confusing expression. 抱歉这个令人困惑的表情。 In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse> . 在简单的英语中,它需要B或继承自class B : public Base<SomeoneElse> SomeoneElse class B : public Base<SomeoneElse>

I don't know if it's the optimal way to achieve this. 我不知道这是否是实现这一目标的最佳方式。 Looks gross to me. 看起来很粗鲁。

However I want to do more. 但是我想做更多。 I want to ensure B is SomeoneElse itself. 我想确保BSomeoneElse本身。 How can I do that? 我怎样才能做到这一点?

Make the constructor (or destructor) of Base private, and then make T a friend . 使Base的构造函数(或析构函数)成为私有,然后使T成为friend This way the only thing that can construct/destruct a Base<T> is a T . 这样,唯一可以构造/破坏Base<T>T

If your class contains some code that says: 如果您的类包含一些代码:

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

Then there will be a compiler error if T is not assignment-compatible with Base . 如果T不与Base分配兼容,则会出现编译器错误。

This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages: 这种检查在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();
}

As to ensuring that Base 's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. 至于确保Base的类型参数正是从它派生的类,这似乎在概念上是有缺陷的。 A class that is acting as a base class can't "talk about" the type that is inheriting it. 充当基类的类不能“谈论”继承它的类型。 It may be inherited more than once via multiple inheritance, or not at all. 它可以通过多重继承而不是一次继承,或者根本不继承。

Two good answers so far. 到目前为止两个好的答案。 Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). 这是另一个使用为某些方法生成自定义访问键的习语(在这种情况下是构造函数)。 It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived. 它提供了正确使用的绝对保证,同时不将基础中的私有方法暴露给派生。

It can also be used to control access to other methods in the base class on a case-by-case basis. 它还可以用于根据具体情况控制对基类中其他方法的访问。

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())
    {}

};

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

相关问题 我可以在这里使用 Curiously Recurring Template Pattern (C++) 吗? - Can I use the Curiously Recurring Template Pattern here (C++)? 如何使用“好奇重复性模板”模式 - How to use the “Curiously recurring template” pattern 奇怪的重复模板模式(CRTP),AutoLists和C ++ - Curiously Recurring Template Pattern (CRTP), AutoLists and C++ 如何将好奇重复模板模式用作桥模式? - How to use Curiously Recurring Template Pattern for Bridge Pattern? 奇怪的重复模板模式多态拷贝(C ++)中的继承 - Inheritance in curiously recurring template pattern polymorphic copy (C++) C ++ BigIntegers和奇怪的重复模板模式问题 - C++ BigIntegers and the Curiously Recurring Template Pattern Issue C ++反复出现的模板模式,语法错误 - C++ Curiously recurring template pattern, syntax error 具有可变参数模板的好奇重复模板模式(C ++) - Curiously recurring template pattern with variadic templates (C++) C ++:奇怪的重复模板模式是什么?并且可以奇怪地重复模板模式取代虚拟功能? - C++: what is the Curiously-Recurring-Template-Pattern? and can Curiously-Recurring-Template-Pattern replace virtual functions? 具有ptrhead的奇怪重复模板模式 - Curiously recurring template pattern with ptrhead
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM