【发布时间】:2021-09-13 16:09:42
【问题描述】:
我是模板编程的新手,偶然发现了这个习语。例如,类似:
class FooBase {
public:
virtual void do_something() = 0;
};
template <class Foo> // Foo is derived from FooBase
void g(Foo& foo) {
static_assert(std::is_base_of<FooBase, Foo>::value);
// ...
foo.do_something();
// ...
}
在我自己看来,这种模式很有用,因为:
- 纯虚函数声明具有显式签名;与 C++20 概念
requires子句(如果有的话)相比,它很容易指定属性、参数和返回类型。 - 这是一个很好的文档;只需阅读
FooBase标头,就可以清楚地了解定义新 Foo 类的要求。 - 可以将所有 Foo 的通用功能重构为同一个
FooBase类。
但是,我担心使用 virtual 函数对性能的影响。我的理解是运行时没有成本,因为函数是从派生类调用的;但链接器将无法内联函数。
另一个缺点是不允许使用虚拟模板函数。
最后,我担心这可能是一种代码异味,因为它使用运行时多态的特性来执行静态检查。 C++20 概念可能是执行此操作的“正确”方法,但由于上述三个原因,它们似乎不太方便。
【问题讨论】:
-
具体执行在哪里?任何具有
do_something成员且在调用中不接受任何参数的类都将受到您的函数模板的欢迎。 -
在这种情况下,
void g(FooBase& foo) { ... }不会做你想做的事吗? -
@StoryTeller-UnslanderMonica 是的,我应该包含一个
static_assert,但在示例中省略了它 -
@TedLyngmo 但是 Foo 的类型在编译时是已知的,所以我不需要使用运行时多态性
-
@NickFP 在您编辑后,我的(现已删除)评论代表您的 “运行时无需成本,因为该函数是从派生类调用的” 不是可靠的陈述,因为任何
FooDerived&都可能是从FooDerived中派生的类型。
标签: c++ templates polymorphism c++-concepts