问题标签 [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 回答
99 浏览

java - Java静态多态(重载)和泛型之间的继承

Java 11(可能无关紧要):

惊人的输出:

为什么Java静态选择不同的方法?

0 投票
2 回答
87 浏览

c++ - 具有转发引用的静态多态性

我正在尝试使用如下所示的简单示例中的静态多态性。

问题是TinpolymorphicCall被推断为Derived,这样任何东西都可以传递给该函数,甚至int。有没有办法只接受Base<Derived>类型?

我尝试使用转发引用和enable_ifon 模板参数,但是我无法推断出Bases 模板参数。

有什么方法可以同时使用转发引用和静态多态性?

编辑:更新了代码示例以包含实际的转发参考以及如何尝试使用它。

显示的错误是:“错误:不完整类型'struct Traits'的无效使用”

链接:https ://godbolt.org/z/3EcS47

0 投票
4 回答
594 浏览

c++ - 如何正确使用“C++ 核心指南:C.146:在类层次导航不可避免的情况下使用 dynamic_cast”

动机

C++ 核心指南建议dynamic_cast在“类层次结构导航不可避免”时使用。这会触发 clang-tidy 抛出以下错误:Do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast].

指导方针继续说:

注意

像其他演员表一样,dynamic_cast被过度使用。喜欢virtual函数而不是强制转换。在可能(不需要运行时解析)和相当方便的情况下,更喜欢静态多态性而不是层次结构导航。

我一直只是在我的基类中使用一个enum命名Kind嵌套,并static_cast基于它的种类执行一个。阅读 C++ 核心指南,“......即便如此,根据我们的经验,这种“我知道我在做什么”的情况仍然是一个已知的错误来源。建议我不应该这样做。通常,我没有任何virtual功能,因此 RTTI 不可用dynamic_cast(例如,我会得到error: 'Base_discr' is not polymorphic)。我总是可以添加一个virtual功能,但这听起来很傻。该指南还说在考虑使用我使用的判别方法之前进行基准测试Kind

基准

我是基准测试的新手,所以我真的不知道自己在做什么。我注意确保virtual和判别版本具有相同的内存布局,并尽我所能防止优化。我选择了优化级别O1,因为任何更高的级别似乎都没有代表性。discr代表歧视或标记。virt代表virtual 这是我的结果:

基准测试结果

问题

所以,我的问题是:当(1)我知道派生类型,因为我在输入函数之前检查了它,以及(2)当我还不知道派生类型时,我应该如何从基类型转换为派生类型。另外,(3)我应该担心这个指南,还是应该禁用警告?性能在这里很重要,但有时并不重要。我应该使用什么?

编辑:

使用dynamic_cast似乎是向下转换的正确答案。但是,您仍然需要知道要向下转换的内容并具有virtual功能。在许多情况下,如果不区分诸如派生类是什么kind,您将不知道。tag(4) 如果我已经必须检查kind我正在查看的对象是什么,我还应该使用dynamic_cast吗?这不是两次检查同一件事吗?(5) 有没有合理的方法来做到这一点tag

例子

考虑class层次结构:

现在在main()

我并不总是需要转换为Add_expr. 例如,我可以有一个打印出任何Binary_expr. 它只需要将其转换为Binary_expr即可获得lhsand rhs。要获取运算符的符号(例如“-”或“+”...),它可以打开kind. 我不知道如何dynamic_cast在这里帮助我,而且我也没有可使用dynamic_cast的虚拟功能。

编辑2:

我已经发布了一个答案get_kind() virtual,这似乎是一个很好的解决方案。但是,我现在为 a 携带大约 8 个字节,vtbl_ptr而不是为标签携带一个字节。class从es 派生的对象实例化Expr将远远超过任何其他对象类型。(6) 这是跳过的好时机vtbl_ptr还是我应该更喜欢安全dynamic_cast

0 投票
0 回答
77 浏览

c++ - 多级 CRTP 中的“未命名成员”不完整类型

我在设计库的 CRTP 继承结构时遇到了不完整的类型错误。我知道这可能通过类型特征来解决,但我什至不知道从哪里开始,并希望在这方面得到一些指导。

粗略地说,AlgGeo是从共享基础继承的两个接口。Alg相当简单,但Geo有点复杂,因为它将派生自 的类作为模板参数Alg。不完整的类型错误与此功能有关。最小的可重现示例

下面的框架说明了手头的问题。

下面是一个A派生类的示例和一个使用示例。

发生错误是因为在compute中找不到该函数Geo<SpathSVD<SomeAlgVariant>, SomeAlgVariant>。我怎样才能解决这个问题?

0 投票
1 回答
80 浏览

c++ - 转发 CRTP 派生类方法的返回类型

我想通过 CRTP 使用“静态多态性”来执行以下操作:

这可行,但我也希望在对象被实例化为的情况下Derived1get_value返回对值的 const 引用而不是返回副本。所以在某种程度上,是一种返回值的“完美转发”。

我试图get_value像这样声明 的返回类型:

但不出所料,GCC 抱怨这是一个invalid use of incomplete type 'struct Derived1'.

有什么办法可以解决这个问题吗?

先感谢您!:)

0 投票
2 回答
120 浏览

c++ - C++ 中的模板化成员变量

通常在编写模板代码时,我发现自己需要将模板类型的实例存储在成员变量中。例如,我可能需要缓存一个值以供以后使用。我希望能够将我的代码编写为:

成员在使用时是专门的。我的问题:

  1. 当前的 C++ 生成编码工具是否可以使用这种模板化成员变量?
  2. 如果没有,是否有任何关于这种语言功能的建议?
  3. 如果没有,是否有任何技术原因导致这样的事情是不可能的?

很明显,我不想列出所有可能的类型(例如在 a 中std::variant),因为这不是生成式编程,并且如果库的用户与作者不同,则不可能。

编辑:我认为这在某种程度上回答了我上面的第三个问题。原因是今天的编译器无法将对象的实例化推迟到整个程序被解析之后: https ://stackoverflow.com/a/27709454/3847255

0 投票
0 回答
27 浏览

c++ - 使用 CRTP 从一组模板类运算符继承

这是本Q/A的后续内容。

我正在接受用户 Jarod42 的建议,template <template<typename> class C, typename T>而不是使用我展示的示例作为问题的答案。

我的代码目前如下所示:

你可以在编译器资源管理器上看到它

我只显示+()and+=()运算符以减少显示的代码量。我希望我的所有运算符都在这个基类中定义,single_member_ops并成为所有从这个基类派生的类的朋友。

我上面的代码示例正在为未为定义的二元运算符定义相关运算符的行生成编译器错误:

看来我可以很好地使用+()and+=()运算符来处理在类及其类型中匹配的所有类型,例如 inA<int>A<int>which 很好。但是,假设我想互换使用它们,例如在以下伪情况下:

我必须做什么,或者我的操作员会怎样才能实现这一目标?我在这里还缺少什么?

0 投票
0 回答
43 浏览

c++ - 为包含模板的 API 提供自定义点的首选方式是什么?

假设我正在编写一个库,并且在某些时候,有一些代码想要对用户提供的类型的对象做一些特定的事情。举swap个例子,虽然函数可以是任意的。重要的是:

  • 这应该是静态多态性(编译时决定)
  • 该库可以提供一个默认实现,即:
    • 适用于许多情况(适用于大多数类型)
    • OR 适用于所有类型,但可能对某些类型有更有效的实现
  • 库的用户应该能够替换这个默认实现

在编译时在 C++ 中有两种主要的方法来做这样的事情:

  • 函数重载
  • 类模板特化

这些都不是理想的:

  • 如果用户定义的类型是类模板,则函数重载是不合适的。功能模板不能部分特化,拥有多个功能模板需要大量的维护工作。
  • 类模板不能很好地处理重载完全没问题的琐碎情况。

因此,我的想法是——为什么不两者兼而有之?事实上,一些 STL 功能提供了 2 种甚至更多的自定义行为方式。典型的 STL 算法提供 3 个:

  • 提供将用作仿函数实现的附加函数参数(通常是 lambda)
  • 为特定类型重载特定运算符
  • 专门属于标准库的特定类模板

在我的情况下,第一个选项(额外参数)是不可能的,因为假定的库不会立即使用该函子。

所以我剩下两种可能的实现重载+专业化的方法:

  • A)库调用函数,默认重载调用主类模板(首先解决重载,然后是类模板)
  • B) 库调用初级类模板(首先解决类模板特化)和初级类模板实现调用(可能重载)函数

问题是 - 哪个实现更好 - A 还是 B?(函数,主要类模板)调用哪个的顺序有什么不同吗?这两种实现中的每一种都有哪些优点/缺点?

0 投票
1 回答
58 浏览

c++ - 如何在 C++ 中用静态多态性代替动态多态性?

假设我有以下代码利用 C++ 中的动态多态性

图形对象.h

矩形.h

矩形.cpp

圈子.h

圈子.cpp

主要的

我的问题是是否有可能让picture数组没有动态多态性,而不是只使用静态多态性并避免使用虚拟方法?我想避免使用虚拟方法的原因是我想避免与访问 vtable 相关的开销。

0 投票
0 回答
87 浏览

c++ - 不同的事件/任务处理方式

一个事件/任务实例是基于一个线程中的一些传入数据创建的,并被发送到另一个线程中进行处理。我正在尝试测量在第二个线程中处理这些事件的不同实现(我想要静态多态性)。

我从std::variantvs. 继承 vs. 其他方式(性能)中获取并修改了一些基准。REPEAT为了更好地了解我介绍了宏的方法之间的区别。现在我有两个问题:

  1. 使用#define REPEAT(x) xie 不重复,为什么所有解决方案都给出相似的结果(我希望 CRTP 和 Concepts 方法成为获胜的方法)?
  1. 使用#define REPEAT(x) REPEAT64(x)给出如下所示的结果。为什么CRTPandConcepts方法的性能与方法相似Virtual?此外,这种方法真的是热循环Switch中最有效的方法吗?while

基准代码: