C++:如何调用这种编译时多态性技术,其优缺点是什么?
C++: How is this technique of compile-time polymorphism called and what are the pros and cons?
在工作中,我遇到过基本上看起来像这样的代码:
#include <iostream>
using namespace std;
enum e_Specialization {
Specialization_A,
Specialization_B
};
template<e_Specialization>
class TemplatedBase {
public:
string foo() { return "TemplatedBase::foo"; }
};
template<>
string TemplatedBase<Specialization_A>::foo() { return "TemplatedBase<Specialization_A>:foo"; }
int main() {
TemplatedBase<Specialization_A> o;
cout << o.foo() << endl;
return 0;
}
输出
TemplatedBase<Specialization_A>:foo
我在任何地方都找不到关于此技术的任何讨论。
代码的创建者主要从事物的优化方面争论,没有虚拟分派发生。在我们的例子中,这种优化不是必需的,但我知道它是如何有用的。
我的问题是:
这种技术是否在任何地方都有记载,它有名字吗?
与继承特化相比,这有什么优势吗?
3。这与 CRTP 有什么关系?在我看来,CRTP 的优点和缺点都是一样的。
至于该技术是否被记录在案(如果您使用 C++11 或更高版本执行此操作,请使用枚举 class),这是一种相当常见的技术,可以在枚举或一个布尔值,然后做你的专业化。
一个明显的区别是,使用这种技术,您显然不能在不修改主要代码的情况下添加更多的专业化。枚举(或枚举 class)只有这么多值。这可能是好事也可能是坏事,具体取决于您是否希望集中跟踪它。但这可以很容易地通过在 class 上进行模板化并封装它来改变,这是第三种选择,它不完全是这种技术,也不涉及 public 继承。
恕我直言,这种技术有其最大的优势,因为您可以选择内联实现。例如:
template<e_Specialization e>
class TemplatedBase {
public:
void bar() {
// code
if (e == Specialization_A) {
...
}
// code
}
};
我在 classes 中看到很多,从一开始就知道它们处于性能关键路径中。可能有一个布尔变量来控制是否发生侵入性性能分析。因为这些分支在编译时是已知的,所以它们被简单地优化了。这是一个很好的方法,因为您仍然可以在同一构建中使用 class 的两个版本(例如,对两者进行 运行 单元测试)。
与继承相比的另一个区别是派生 classes 可以在需要时轻松添加状态。这种技术目前需要专门化整个 class 来添加状态。同样,这可能是好事也可能是坏事;如果您不需要打破这些限制,那么限制更多的设计是好的。您可以轻松更改设计以启用添加额外状态:
template <e_Specialization e>
struct ExtraState {};
template <e_Specialization e>
class TemplatedBase : private ExtraState<e> {
...
第三个小例子是您没有公开任何继承关系。这大部分很小,但请记住,您可以获得诸如切片甚至隐式 reference/pointer 转换之类的东西。对于这项技术来说,这是一个非常严格的胜利。
总而言之,我会说:
- 如果您利用一次实现某项功能并内联写入差异而没有性能损失,那就是一个胜利
- 如果你想在你的设计中明确说明实现数量有限,这是一个胜利。
如果这些都不是真的,那么与仅使用继承相比,该设计有点非正统且更复杂一些,尽管它实际上并没有任何明显的技术劣势。所以如果你周围有很多初级开发人员,这段代码可能更难阅读。
在工作中,我遇到过基本上看起来像这样的代码:
#include <iostream>
using namespace std;
enum e_Specialization {
Specialization_A,
Specialization_B
};
template<e_Specialization>
class TemplatedBase {
public:
string foo() { return "TemplatedBase::foo"; }
};
template<>
string TemplatedBase<Specialization_A>::foo() { return "TemplatedBase<Specialization_A>:foo"; }
int main() {
TemplatedBase<Specialization_A> o;
cout << o.foo() << endl;
return 0;
}
输出
TemplatedBase<Specialization_A>:foo
我在任何地方都找不到关于此技术的任何讨论。
代码的创建者主要从事物的优化方面争论,没有虚拟分派发生。在我们的例子中,这种优化不是必需的,但我知道它是如何有用的。
我的问题是:
这种技术是否在任何地方都有记载,它有名字吗?
与继承特化相比,这有什么优势吗?
3。这与 CRTP 有什么关系?在我看来,CRTP 的优点和缺点都是一样的。
至于该技术是否被记录在案(如果您使用 C++11 或更高版本执行此操作,请使用枚举 class),这是一种相当常见的技术,可以在枚举或一个布尔值,然后做你的专业化。
一个明显的区别是,使用这种技术,您显然不能在不修改主要代码的情况下添加更多的专业化。枚举(或枚举 class)只有这么多值。这可能是好事也可能是坏事,具体取决于您是否希望集中跟踪它。但这可以很容易地通过在 class 上进行模板化并封装它来改变,这是第三种选择,它不完全是这种技术,也不涉及 public 继承。
恕我直言,这种技术有其最大的优势,因为您可以选择内联实现。例如:
template<e_Specialization e>
class TemplatedBase {
public:
void bar() {
// code
if (e == Specialization_A) {
...
}
// code
}
};
我在 classes 中看到很多,从一开始就知道它们处于性能关键路径中。可能有一个布尔变量来控制是否发生侵入性性能分析。因为这些分支在编译时是已知的,所以它们被简单地优化了。这是一个很好的方法,因为您仍然可以在同一构建中使用 class 的两个版本(例如,对两者进行 运行 单元测试)。
与继承相比的另一个区别是派生 classes 可以在需要时轻松添加状态。这种技术目前需要专门化整个 class 来添加状态。同样,这可能是好事也可能是坏事;如果您不需要打破这些限制,那么限制更多的设计是好的。您可以轻松更改设计以启用添加额外状态:
template <e_Specialization e>
struct ExtraState {};
template <e_Specialization e>
class TemplatedBase : private ExtraState<e> {
...
第三个小例子是您没有公开任何继承关系。这大部分很小,但请记住,您可以获得诸如切片甚至隐式 reference/pointer 转换之类的东西。对于这项技术来说,这是一个非常严格的胜利。
总而言之,我会说:
- 如果您利用一次实现某项功能并内联写入差异而没有性能损失,那就是一个胜利
- 如果你想在你的设计中明确说明实现数量有限,这是一个胜利。
如果这些都不是真的,那么与仅使用继承相比,该设计有点非正统且更复杂一些,尽管它实际上并没有任何明显的技术劣势。所以如果你周围有很多初级开发人员,这段代码可能更难阅读。