问题标签 [static-polymorphism]

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.

0 投票
1 回答
58 浏览

c++ - 如果使用 CRTP,派生类方法是否会覆盖该方法的基类版本?

几天前,我发现了一个有趣的 C++ 结构,名为Curiously Recurring Template Pattern(通常缩写为 CRTP)。从那时起,我一直试图完全理解这个技巧是如何工作的。

假设我有以下代码片段

CRTP 背后的所有“魔力”显然都在行static_cast<T*>(this)->draw()。但它是如何详细工作的?我的理解如下。假设我有Circle c.

如果编译器看到这个声明,这是他GraphicalObject用参数实例化模板的信号Circle。我认为这会导致GraphicalObject<Circle>编译器创建结构

draw因此创建了具有该方法的特殊版本的 struct 。该结构GraphicalObject<Circle>构成该结构的基础Circle结构。

在第二步中创建结构的实例c,即调用隐式构造函数。由于首先调用的是从该结构的隐式构造函数继承的事实。在我看来,这会导致创建对象内部的实例。这样对吗?然后我认为struct中声明的方法覆盖了struct中声明的方法。但这对我来说没有意义。我宁愿期望来自 的方法的“专业”版本不会被覆盖。请你能告诉我我对 CRTP 工作原理的理解有什么问题吗?CircleCircleCircleGraphicalObject<Circle>GraphicalObject<Circle>cdrawCircledrawGraphicalObject<Circle>drawGraphicalObject<Circle>

0 投票
1 回答
103 浏览

c++ - 使用 std::variant 的静态多态性

我正在尝试使用 std::variant 实现类似静态多态的东西。我想声明使用 VARIANT_METHOD 或 VARIANT_METHOD_CONST 的方法,这些方法应该采用返回类型、方法名称、参数和限定符。

我不能声明两个具有相同名称但具有不同参数的方法。我想写这样的东西:

0 投票
1 回答
69 浏览

c++ - 在模板类中使用 std::conditional 的问题

我正在尝试使用非类型模板参数定义模板类。然后我使用这个模板参数确定这个类的成员的类型std::conditional。我遇到了一些编译时错误。

下面是MWE。在这个 MWE 中,我试图根据条件分别为真(结构化)或假(非结构化)来制作FiniteElementList模板类的成员 。类 ,包含一些成员和友元函数,这些函数只是暂时声明的,可能会在稍后阶段定义。Meshstd::vectorstd::listMesh

MWE

汇编:

我正在尝试使用 clang 编译器进行如下编译

c++ -O3 -Wall -Wextra -Wpedantic -std=c++17 mesh_structure.cpp -o mesh_structure

我遇到了以下错误

奇怪的是,如果我Mesh<StructuredUnstructured::kStructured> structured;main()函数中删除第二行,代码就会编译。我不太明白这里出了什么问题。任何帮助将不胜感激。

谢谢你。

0 投票
1 回答
49 浏览

c++ - 我可以使用模板成员函数作为 CRTP 的替代方法来实现静态多态性吗?

我想在 C++ 中使用静态多态性来实现模板方法模式。

现在我有两个课程AB它们非常相似。它们具有相同的公共 API 和完全相同的私有数据成员列表。大多数公共成员函数的实现也是相同的,但对于其中一些,这两个类的实现略有不同。

情况看起来有点像这样:

我现在想通过将所有共享代码和数据成员移动到基类并从基类中委托给子类特定的成员函数来减少代码重复。也就是说,像这样:

我知道我可以使用CRTP以类似于以下方式解决此问题:

现在谈谈我的问题。

是否可以在不制作Base模板类的情况下达到相同的结果?我可以使用例如模板成员函数来完成同样的事情吗?

0 投票
0 回答
42 浏览

class - 使用模板将多态类重写为一个类(编译时多态)

在我当前的代码中,我使用运行时多态性从 LightBase 类创建不同的“光”子类型。然而,lighttypes 在编译时是已知的(预处理器选择正确的变体)。所以我认为它确实不是正确的工具,因为它很慢(虚拟 getter 函数的 vtable 查找)并且可以在编译时完成。我只是不知道如何...可以用模板完成吗?我在模板编程方面没有太多经验,所以我不知道有什么可能。

本质上,我想实例化一个 NormalLight 或 SpecialLight 类型的子类,它们具有与 LightBase 相同的功能,但对一组不同的常量进行操作:

在一个函数中,我可以有条件地检查模板参数(我猜),但它是一个类定义。此外,这个东西应该在 C++11 中编译。有任何想法吗?

0 投票
1 回答
64 浏览

c++ - 是否可以在没有动态多态性的情况下在 C++ 中实现状态设计模式?

假设我有以下 C++ 代码

假设我想根据一些外部事件在运行时algorithm_A和运行时之间切换algorithm_B(基本上我将实现状态设计模式)。所以algorithm指针指向algorithm_Aalgorithm_B对象。我的问题是是否有任何方法可以实现在运行时动态切换算法的能力,而无需公共接口中的虚拟方法,例如奇怪的重复模板模式?

0 投票
1 回答
223 浏览

c++ - C++17 std::variant 比动态多态性慢?

我正在关注这个博客,并试图将动态多态性代码替换为使用std::variantand std::visit。但我无法让std::variant+std::visit比虚拟结构 impl 更好地工作。它慢了大约1.3-1.5 倍!(GCC 10.3 -O3 C++17)

用例如下。假设我们正在比较两个表的第 i 行和第 j 行。表可能具有异构类型的列。假设我们可以访问列缓冲区。我正在做的是测试,

对于动态多态性,我有以下intfloat

这被转换为std::variant+std::visit如下。

我在这里进行了基准测试 https://quick-bench.com/q/u-cBjg4hyQjOs6fKem9XSdW7LMs

有人可以解释为什么这个std::variant+std::visit选项比动态多态方法慢吗?我期待否则!我的方法和/或基准有问题吗?

0 投票
1 回答
61 浏览

c++ - 编译时接口(非虚拟)

如果你想为同一个对象有不同的公共接口,你可以使用虚拟基类。但是那些有开销(内存和空间)。

可以将对象转换为具有不同访问修饰符和相同大小的类。这通常在纯 C 中完成,并带有隐藏实现细节的结构。但是这个解决方案本质上是不安全和未定义的行为,可能很难找到错误,因为优化器如果完成了它的工作,可能无法很好地处理禁止的别名(相同的内存位置具有不同的名称)。当访问修饰符不同时,一些编译器可能会重新排列内存布局。像 dynamic_cast<>、reinterpret_cast<> 和 bit_cast<> 这样的强制转换只允许用于某些类。

现在我找到了至少一种解决方案,哪种使用超类而不是基类作为接口,并且似乎是合法的。这是真的?有没有更简单的方法可以到达那里?

复杂的.h:

视图1.h:

视图2.h:

视图3.h:

组合.h:

测试.cpp:

输出是:

视图只能看到它们各自的成员变量(其他成员受保护)。允许从 Combine 转换为基类(3 个视图)。Complex 类没有特殊要求,甚至没有标准布局或默认可构造。

Complex 类包含所有成员和实现,但必须构造 Combined 类,以便所有视图都是静态基类。

在显示的示例中,视图只能从具有 view1/2/3() 函数的类内部创建,因为继承受到保护。可以进行公共继承,但必须显式地使所有成员对受保护的视图不可见。并且可以看到视图的链接顺序。但优点是,可以直接从组合类中转换视图。这也许也可以通过运算符 View1& 转换运算符来实现?

由于视图知道对象的实际构造(动态)类(=Combined),因此可以从视图指针中进行破坏(此处未实现)。

这些视图仅适用于编译时已知的对象类,否则需要使用传统的虚拟解决方案。

对于静态(非开销)视图,是否有一种更简单(合法)的方式,使用起来很舒服?

(人们总是可以回退到朋友功能)