[英]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. 我想确保
B
是SomeoneElse
本身。 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.