即时推导

发布于 2024-08-14 16:10:16 字数 954 浏览 19 评论 0原文

有一个不太常见的 C++ 习惯用法,我过去曾使用过几次,效果很好。我似乎不记得它是否有一个常用的名称来描述它。

它与 mixinsCRTP类型擦除,但不是具体的任何这些东西。

当您想要向类添加一些实现,但又不想将其放入该类或其派生的任何类中时,就会出现问题。原因之一可能是该类可能是继承层次结构的一部分,其中实现应该只发生一次。

目前,暂且不考虑诸如层次结构是否应该具有具体的非叶类,或者在某些情况下虚拟继承是否是一种选择等问题,我知道有一种解决方案可以在派生自的模板类中提供实现它的模板参数。这样,您就可以在创建实例时使用模板,但只能通过指针或对其基类之一的引用来使用该对象(这就是松散意义上的类型擦除的用武之地)。

一个例子可能是你有一个侵入性的引用计数。您的所有类都派生自引用计数接口,但您只希望引用计数本身以及引用计数方法的实现出现一次,因此您将它们放入派生模板中 - 让我们称之为 ImplementsRC;。现在您可以像这样创建一个实例:

ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();

我掩盖了诸如由多个模板化重载形成的转发构造函数等内容。

因此,希望我已经清楚地说明了这个习惯用法是什么。现在回到我的问题 - 这个习语是否有一个公认的或至少普遍使用的名称?

There's a less common C++ idiom that I've used to good effect a few times in the past. I just can't seem to remember if it has a generally used name to describe it.

It's somewhat related to mixins, CRTP and type-erasure, but is not specifically any of those things.

The problem is found when you want to add some implementation to a class, but you don't want to put it in the class, or any class it derives from. One reason for this might be that the class could be part of an inheritance hierarchy where the implementation should only occur once.

Setting aside, for the the moment, issues such as whether a hierarchy should have concrete non-leaf classes, or whether virtual inheritance may be an option in some cases, I know that one solution to provide the implementation in a template class that derives from its template parameter. This then allows you to use the template when you create an instance, but then only ever use the object by pointer or reference to one of its bases (that's where the type erasure, in a loose sense, comes in).

An example might be that you have an intrusive reference count. All your classes derive from a ref count interface, but you only want the ref count itself, and the implementation of your ref count methods, to appear once, so you put them in the derived template - let's call it ImplementsRC<T>. Now you can create an instance like so:

ConcreteClass* concrete = new ImplementsRC<ConcreteClass>();

I'm glossing over things like forwarding constructors formed of multiple templated overloads etc.

So, hopefully I've made it clear what the idiom is. Now back to my question - is there an accepted, or at least generally used, name for this idiom?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

蓝梦月影 2024-08-21 16:10:16

这是一个有趣的想法。然而,我不会在这里给你一个已经建立的模式的名称,相反,我将(在某种程度上)解释为什么我认为它还没有一个。

它有什么作用?

这是避免可怕的钻石继承的一个非常好的方法。

由于对该方法的目的显然存在一些困惑,让我详细说明为什么我认为这就是它的目的:

class RefCounted
{
  virtual void addReference() = 0;
  virtual void removeReference() = 0;
};

class B: public RefCounted {};
class C: public RefCounted {};

class Diamond: public B, public C {};

现在,我们遇到了一个问题。如果我们将 RefCounted 的实现放在此类中,它就会成为基类而不是接口,因此我们必须使用虚拟继承,否则数据成员将被重复(存在于两个类中) B 和 C)。

因此,我们的想法是将实施推迟到最后一刻。

优点:

  • 无需尝试事后猜测 B 或 C 的使用:那里不需要虚拟继承。
  • 如果您忘记添加实现,编译器会很好地提醒您,因此无需担心。

不方便:

  • 给客户端增加负担:你最好有一个工厂来创建你的对象,特别是因为一个对象可能实现各种接口!请注意,这可能通过模板元编程(或多或少)自动实现,或者可以简单地由类作者提供。

提供示例:

// d.h
class D: public B, public C
{
public:
  typedef ImplementRC<D> concrete_type;
  static concrete_type Build(int, int); // Named Constructor idiom

private:
  D(int,int);
}; // class D

// main.cpp
D::concrete_type myD = D::Build(1,2);

那么名字是什么?

我想不出任何与此完全匹配的内容。已经提到了 Bridge 和 Decorator,但这非常特殊,而且确实不是面向对象的(例如,它不会在 Java 中发生,因为你没有多重继承),所以我怀疑这个术语是否会被发现在 GoF 的书中。

另外,它并不是真正的 CRTP,因为 CRTP 中有一种循环(基础知道其派生类),但这里不会发生 > >我们确实是严格线性的!

然后,这当然不是 Pimpl 的惯用语,它建议将实现隐藏在远离客户端的地方,而使用模板来实现,只需将其扔到脸上即可! (不过,该模板可以使用 Pimpl 作为内部细节)

我谦虚地建议 jiti 用于 Just In Time Implement,它以某种方式模仿了标题,但更接近我认为的要点,这里的推导只​​是一个工具而不是目标。

无论如何,有趣的想法。

It is an interesting idea. However I am not going to give you the name of an already established pattern here, on the very contrary I am going to explain (somewhat) why I don't think it already has one.

What does it do?

It is a very nice way to avoid the dread diamond inheritance.

Since there is some confusion apparently as to the purpose of the method, let me elaborate why I think this is its purpose:

class RefCounted
{
  virtual void addReference() = 0;
  virtual void removeReference() = 0;
};

class B: public RefCounted {};
class C: public RefCounted {};

class Diamond: public B, public C {};

Now, we here have a problem. If we put the implementation of RefCounted right in this class, it becomes a base-class instead of an interface, and thus we have to use virtual-inheritance or the data members will be duplicated (present in both B and C).

The idea is thus to defer the implementation to the last moment.

Advantages:

  • No need to try to second-guess the use of B or C: virtual inheritance is unnecessary there.
  • The compiler will nicely remind you if you forget to add the implementation, so no need to worry about that.

Inconvenient:

  • Put the burden on the client: you'd better have a factory to create your objects, especially since one object may implement various interfaces!!! Note that this might be automated with template meta-programming (more or less) or can simply been provided by the class author.

Example of providing:

// d.h
class D: public B, public C
{
public:
  typedef ImplementRC<D> concrete_type;
  static concrete_type Build(int, int); // Named Constructor idiom

private:
  D(int,int);
}; // class D

// main.cpp
D::concrete_type myD = D::Build(1,2);

So what's the name ?

I can't think of anything that exactly matches this. Bridge and Decorator have been mentionned but this is quite special, and indeed not so OO-oriented (for example it won't happen in Java since you don't have Multi-Inheritance), so I doubt the term is going to be found in the GoF's book.

Also, it's not really the CRTP because there is a kind of loop in the CRTP (base being aware of its derived class) that does not happen here > we indeed are strictly linear!

And then, it's certainly not the Pimpl idiom, which proposes to hide the implementation away from the client while using a template for the implementation just throw it to its face! (The template could use Pimpl as an internal detail though)

I humbly suggest jiti for Just In Time Implementation, which mimicks the title somehow, but is closer to the point I think, derivation here being just a tool rather than a goal.

Interesting idea anyhow.

千里故人稀 2024-08-21 16:10:16

我肯定会认为这是一个 mixin,Bruce Eckel 也会认为这是一个 mixin (http: //www.artima.com/weblogs/viewpost.jsp?thread=132988)。

在我看来,使其成为 mixin 的原因之一是它仍然是单继承,这与使用 MI 来实现类似的东西不同。

I'd definitely consider this to be a mixin, as would Bruce Eckel (http://www.artima.com/weblogs/viewpost.jsp?thread=132988).

In my opinion one of the things that makes this a mixin is that it's still single inheritance, which is different from using MI to achieve something similar.

似梦非梦 2024-08-21 16:10:16

我不确定它有一个名字,正如 gf 所说,它看起来有点像桥接模式。这几乎就像您将功能挂钩到基类一样。

我建议为此命名一个新名称:pimp 习语。当你在拉皮条的时候你的基类;)

I'm not sure this has a name, as gf suggested it's looks a bit like the bridge pattern. It's almost like your hooking on functionality to the base class.

I suggest a new name for this, the pimp idiom. As you're pimping your base class ;)

つ低調成傷 2024-08-21 16:10:16

您是否在寻找装饰器模式

基本上,装饰器是一个包含另一个对象并扩展某些方法的功能的对象。然后,方法调用将转发到所包含的方法。

Are you looking for the Decorator pattern?

Basically the decorator is an object that encloses another object and extends the functionality of certain methods. The method calls are then forwarded to the enclosed method.

今天小雨转甜 2024-08-21 16:10:16

这是一个混合

This is a mixin

樱娆 2024-08-21 16:10:16

查看您的引用计数示例,您可能会对 CComObject<> 感到高兴。它是 ATL 包含的几个提供 IUnknown 实现的模板类之一。它还使用策略类来改变行为。自然地,尝试通过 Google 搜索 CComObject 概念的信噪比非常低,因为它是如此普遍。这篇 MSDN 文章可能会为您提供更多“关键字”来帮助您进行搜索。

http://msdn.microsoft.com/en-us /library/c43h4867(VS.80).aspx

[注意:需要明确的是 - 我并不是建议他使用 CComObject,我建议它是另一个流行的示例相同的概念,因此可能已在模式书籍或文章中引用]

Looking at your reference counting example, you may get some joy looking into CComObject<> which is one of a few template classes that ATL contains to provide the implementation of IUnknown. It also uses policy classes to vary the behaviour. Naturally the signal-to-noise ratio trying to Google about the concept of CComObject is very low because it's so ubiquitous. This MSDN article may give you some more "keywords" to aid any searching.

http://msdn.microsoft.com/en-us/library/c43h4867(VS.80).aspx

[NB: Just to be clear - I'm not suggesting he uses CComObject, I'm suggesting it is another popular example of the same concept and therefore may have been referenced in a patterns book or article]

瑾夏年华 2024-08-21 16:10:16

看起来像Pimpl 习语?也许以不寻常的方式使用。

Looks like Pimpl idiom? Maybe used in an unusual way.

情域 2024-08-21 16:10:16

我不确定,但它是“空成员 C++ 优化”吗?

这种行为是使用类模板私有继承来实现的。

Scott Meyer 在名为“Counting Objects in C++” 的杂志文章中对此进行了解释。

I am not sure but is it "empty member c++ optimization" ?

and such kind of behaviour is implemented using class templates and private inheritance.

It is explained in Magazine Article named "Counting Objects in C++" by Scott Meyer.

腻橙味 2024-08-21 16:10:16

回答我自己的问题。疯狂的第一个迹象? - 不,在此之前有几个迹象;-)

无论如何,自从我最初发帖以来已经过去了很长时间,无论如何我或多或少是一个不同的人。

我发现我已经选定了这个名字:mixover。我发现这非常适合,并且可以被认为是 mixin 的改进,而不是专属于更一般的概念。

我最近经常使用它们,所以我想我会回来更新这个线程。

Answering my own question. First sign of madness? - no there were several signs before this ;-)

Anyway, it's been so long since I originally posted I'm more-or-less a different person anyway.

I've found that I've settled on the name, mixover. I've found this fits very nicely and can be considered a refinement of mixin, rather than being exclusive to the more general concept.

I've been using them a lot recently so I thought I'd come back and update this thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文