问题标签 [crtp]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - c++派生类的类型列表
使用 CRTP(奇怪的重复模板模式),您可以为基类提供派生类的知识。创建一个数组来存储从基类派生的每个类的实例并不难(参见示例)
我想知道是否可以创建所有派生类类型的 Typelist(请参阅http://www.research.ibm.com/designpatterns/pubs/ph-jun00.pdf)。问题是,每次编译器看到一个派生自Base
它的新类时,都需要将新类型附加到列表中,但类型列表是不可变的(可以创建一个附加新类型的新列表,但添加据我所知,列表中的元素是不可能的。最后我想要这样的东西:
最终目标是能够遍历所有派生自Base
.
c++ - C++:CRTP 析构函数?
在一个项目中,我有以下问题:
我有一个非常简单的继承方案(我需要继承而不是组合):
类基础
-> 类 DerivedA
-> 类 DerivedB
-> 类 DerivedC
A、B 和 C 从 Base 派生,仅此而已。所以现在我有两个选择:
具有虚拟性的公共继承
没有虚拟性的私有继承
由于某些优化原因(我需要大量内联),我不想要虚拟性......而且我不想要私有继承。我认为剩下的唯一选择是 CRTP。但是基类有大约 300 个函数,在其中实现 CRTP 将是一个真正的痛苦。
所以我想知道以下解决方案是否有效:我只在基类的析构函数中使用 CRTP:
其中 TCRTP 将是 DerivedA、B 或 C,我进行公共继承。完全没问题,还是有问题?
非常感谢你。
c# - 如何在 C# 中编写一个好的奇怪重复模板模式 (CRTP)
不久前,我想创建自己的数据映射器,它比普通的 ORM 简单得多。在这样做的过程中,我发现需要访问我的基类中继承类的类型信息。我的第一个想法是反射,但它太慢了(如果你使用反射,请查看Fasterflect,因为它“几乎”消除了反射的性能问题)。
所以我转向了一个解决方案,后来我发现它有自己的名字:The Curiously Recurring Template Pattern。这主要解决了我的问题,但是学习如何正确实现这种模式有点挑战。我必须解决的两个主要问题是:
1)如何让我的消费代码与我的通用对象一起工作,而无需知道创建对象的通用参数?
2) 如何在 C# 中继承静态字段?
具有挑战性的部分实际上是弄清楚问题。一旦我意识到我需要做什么,解决这些问题就很容易了。如果您发现自己需要 CRTP,您可能会发现自己需要回答这些问题……它们似乎齐头并进。
c++ - 带有 CRTP 的 C++ SFINAE,G++ 编译错误
我想知道以下代码是否有效。
最初的意图是,我喜欢一个基类,它将对某个成员的调用分派给派生类成员(如果存在),或者如果派生类没有该成员,则回退到默认行为。另一个用途是这个基类可以自己使用,Derived
模板参数成为实现策略。clang++
无论如何,下面的 MWE 可以在、Intelicpc
和 MSVS上正确编译和运行。但是,它失败了g++
(从 4.4 到 4.6,我使用过的任何版本),并在问题末尾显示错误消息。
如果我将call
点 (1)、(2)、(3) 更改为call_dispatch
(这是我最初所做的那种事情),g++
就不会再抱怨了。我认为调度函数和调用者具有相同的名称不是一个好习惯。我只是好奇它是否会起作用,并且好奇地尝试一下(我不知道这个想法是如何产生的)。我这样做的理由是,在品脱 (1) 处,call
使用一个参数调用,因此重载决议将不匹配其调用者,即零参数一。它也不会匹配SFINAE
点 (2) 处的那个,因为D2
没有成员,然后它应该匹配点 (3) 处的那个。就像 (1)-(3) 被命名的情况一样call_dispatch
。
但g++
不同意我和其他编译器。那么,是不正确的实现g++
还是代码本身无效?除了错误信息真的很混乱。void (B<D2>::*)()
和从何&B<D2>::call
而来?Int 他调用的成员指针被定义为D2
' 的成员。
错误:
编辑
虽然我还没有完全理解上面的代码出了什么问题。但我认为还有另一种方法,无需专门构建 SFINAE 类,但存档相同的效果。
基本上,因为D1
和D2
都是从 派生的B
,所以表达式&Derived::call
总是会被解析。在D1
它解析为&D1::call
,然后使用模板版本成员。在D2
中,它没有自己的,call
因此&D2::call
解决
了 所以使用默认调用。&B::call
&D2::call
B::call
可以帮我看看这个新代码是否有任何缺陷?
c++ - 如何统计一个模板类的 CRTP 子类数量?
有谁知道使用 CRTP 计算对象子类数量的方法?
假设我们有一个类似于以下的设置:
等等,这样,使用 TMP,我们可能有一个常数 ( ObjectSubClassCount
) 来表示子类的总数?
有谁知道这样做的方法?
编辑:我想稍后将结果用作模板参数,所以我需要使用 TMP 来完成...
c++ - 防止用户从不正确的 CRTP 基础派生
我想不出一个合适的问题标题来描述这个问题。希望下面的详细信息可以清楚地解释我的问题。
考虑以下代码
尽管 的定义D2
是故意错误的,但它会编译并运行。第一次调用将输出一些预期未初始化d2.call_impl()
的随机位。D2::data_
第二次和第三次调用都将输出100
.data_
我明白为什么它会编译和运行,如果我错了,请纠正我。
当我们进行调用d2.call()
时,调用被解析为Base<D1>::call
,并且将this
转换为D1
和调用D1::call_impl
。因为D1
确实是派生形式Base<D1>
,所以在编译时强制转换很好。
在运行时,在强制转换之后this
,虽然它确实是一个D2
对象,但它被视为好像它是D1
,并且调用D1::call_impl
将修改应该是的内存位D1::data_
,并输出。在这种情况下,这些位恰好在哪里D2::data_
。我认为第二个d2.call_impl()
也应该是未定义的行为,具体取决于 C++ 实现。
关键是,这段代码虽然本质上是错误的,但不会给用户任何错误的迹象。我在我的项目中真正做的是我有一个 CRTP 基类,它就像一个调度引擎。库中的另一个类访问 CRTP 基类的接口,比如call
,call
并将调度到call_dispatch
该接口,可以是基类默认实现或派生类实现。如果用户定义的派生类,比如说D
,确实是从Base<D>
. 如果它源自Base<Unrelated>
whereUnrelated
不是源自Base<Unrelated>
. 但它不会阻止用户编写上述代码。
用户通过从基 CRTP 类派生并提供一些实现细节来使用该库。当然还有其他设计方案可以避免上述错误使用的问题(例如抽象基类)。但是让我们暂时把它们放在一边,相信我因为某种原因我需要这个设计。
所以我的问题是,有什么方法可以防止用户编写错误的派生类,如上所示。也就是说,如果用户编写了一个派生的实现类,比如D
,但他是从 派生的Base<OtherD>
,那么将引发编译时错误。
一种解决方案是使用dynamic_cast
. 但是,这是广泛的,即使它有效,它也是一个运行时错误。
c++ - Boost.Parameter:命名模板参数与 CRTP 结合
警告:前面需要冗长的介绍来解释问题。在 Vandevoorde 和 Josuttis 的 ch 16.1 中首次描述的命名模板参数习语可以使用Boost.Parameter库方便地编写
上面的代码允许通过命名它们和覆盖BreadSlicer
任意顺序的可选模板参数。这使得使用许多默认参数进行基于策略的设计非常方便。Policy1_is
Policy2_is
为了避免基于策略的设计非常微妙的 ODR 违规(有关解释,请参阅 Alexandrescu 的这篇旧帖子),我希望能够在命名模板参数上应用 CRTP 模式:
但是,上面的 Boost.Parameter 实现无法编译,因为一些内部 static_assert 失败并显示类似 (VC10 SP1) 的消息
'main::CuriousBreadSlicer' :不允许将未定义的类作为编译器内在类型特征 '__is_base_of' 的参数
问题:这个静态检查可以关闭吗?通过宏或模板技巧?
至于可能的解决方法:
- 上面的代码在功能上等同于这个手写代码。对于该代码,CRTP 模式确实有效。然而,它需要大量的样板代码,Boost.Parameter 库可以方便地自动化。
- 我可以要求 CRTP 参数在模板参数列表中始终排在第一位,而不是将其包装在一个
Policy1_is
类中。这解决了编译时错误,但它失去了覆盖的顺序独立性。
所以看起来我就是高尔夫球手所说的“在俱乐部之间”。哪种解决方案最好?
c++ - 带有模板叶类的奇怪重复模板
我正在考虑为我的应用程序使用奇怪的重复模板模式。但是,我希望这些类对用户定义的类型进行操作。我想了解是否可以创建类似于下图所示的结构:
上面的代码编译失败,出现以下错误:
'模板类 BaseTrajectoryPoint' 的模板参数列表中参数 1 的类型/值不匹配</p>
有没有其他解决问题的方法?我想使用静态多态性,但我更愿意在基类中定义所有可能的方法。
c++ - C++ 中带有混入的奇怪循环继承
在这里解读循环继承的好方法是什么?
它失败(gcc 4.7.0),因为在尝试从它继承TrafficLight
时是不完整的类型。HasImportance
真正的问题是 HasImportance 需要知道
neighbors()
. 如果HasImportance
继承自
Node
,则它认为neighbors()
返回 的列表
Node*
,而不是TrafficLight*
,因此不知道它可以调用receive_importance()
这些项目。HasImportance
如果根本不继承类似的问题。
顺便说一句,我想做的是做一些混合来帮助轻松定义各种不同类型的图形,并分别对每个混合进行单元测试。例如,我应该能够通过编写类似class TrafficLight : public HasImportance, HasState<3>,
virtual Node { }
.
我想出了三种方法来解决这个问题,但看起来都很丑。(1)
static_cast<NodeType*>
。(2)TrafficLight
将其传递
this
给HasImportance
它的构造函数。这样,
HasImportance
根本不需要继承;它只存储一个指向 (ahem) 本身的指针,模板参数提供指针的类型。(3) 制作Node
一个类模板,如下所示:
编译后并没有引入 的无偿副本this
,但似乎……有点太好奇了。
这里有代码气味吗?我应该以完全不同的方式处理这些图表吗?
c++ - 如何将模板参数传递给 CRTP?
在以下代码中:
如何编写 CRPTInt 以便我可以传入模板化参数,然后将在派生定义中继续?
谢谢,
吉姆