使用基于策略的设计,EncapsulatedAlgorithm
:
template< typename Policy>
class EncapsulatedAlgorithm : public Policy
{
double x = 0;
public:
using Policy::subCalculate;
void calculate()
{
Policy::subCalculate(x);
}
protected:
~EncapsulatedAlgorithm() = default;
};
可能有一个执行子计算的策略Policy
。算法不需要子计算:在某些情况下可以使用它来加速算法收敛。因此,为了对此进行建模,假设有三种策略。
只是“记录”某事的人:
struct log
{
static void subCalculate(double& x)
{
std::cout << "Doing the calculation" << endl;
}
};
计算:
struct calculate
{
static void subCalculate(double& x)
{
x = x * x;
}
};
和一个把它们全部带到黑暗中并绑定它们:D - 它完全没有:
struct doNothing
{
static void subCalculate(double& x)
{
// Do nothing.
}
};
以下是示例程序:
typedef EncapsulatedAlgorithm<doNothing> nothingDone;
typedef EncapsulatedAlgorithm<calculate> calculationDone;
typedef EncapsulatedAlgorithm<loggedCalculation> calculationLogged;
int main(int argc, const char *argv[])
{
nothingDone n;
n.calculate();
calculationDone c;
c.calculate();
calculationLogged l;
l.calculate();
return 0;
}
here是实例。我尝试在启用优化的情况下检查gcc
生成的汇编代码:
g++ -S -O3 -std=c++11 main.cpp
但是我对于大会没有足够的了解以确定地解释结果 - 结果文件很小并且我无法识别函数调用,因为所有策略的静态函数的代码都是内联的。
我能看到的是,当没有为主函数设置优化时,有一个call
和一个与'doNothing :: subCalculate'相关的后续leave
call _ZN9doNothing12subCalculateERd
leave
以下是我的问题:
g++ -S
喷出的内容,我从哪里开始学习? main.s
中哪些是哪些行?subCalculate
而不是doNothing
),但是在策略的情况下,策略名称明确指出功能不会做任何事情。否则我需要输入像enable_if
等类型的特征,只是为了排除单个函数调用。 答案 0 :(得分:5)
我去了http://assembly.ynh.io/,显示了汇编输出。我
template< typename Policy>
struct EncapsulatedAlgorithm : public Policy
{
void calculate(double& x)
{
Policy::subCalculate(x);
}
};
struct doNothing
{
static void subCalculate(double& x)
{
}
};
void func(double& x) {
EncapsulatedAlgorithm<doNothing> a;
a.calculate(x);
}
得到了这些结果:
.Ltext0:
.globl _Z4funcRd
_Z4funcRd:
.LFB2:
.cfi_startproc #void func(double& x) {
.LVL0:
0000 F3 rep #not sure what this is
0001 C3 ret #}
.cfi_endproc
.LFE2:
.Letext0:
好吧,我只在组装中看到两个操作码。 rep
(不知道那是什么)和结束功能。似乎G ++编译器可以轻松地优化函数体。
答案 1 :(得分:3)
为了能够阅读g ++ -S喷出的内容,我从哪里开始学习?
此网站不适用于推荐阅读材料。谷歌“x86汇编语言”。
是否将空函数优化掉,而main.s中的那些是那些行?
启用优化器的时候,生成的.S中不会有任何行。你已经在未经优化的输出中找到了这个电话....
事实上,即使是用于进行乘法的策略也可能被删除,因为编译器应该能够计算出你没有使用结果值。添加代码来打印x的值,并从编译时无法知道的某个值中播种x(在这样的小实验程序中使用argc通常很方便,那么你将至少强迫编译器留下功能重要的代码。
这个设计是O.K。?
这取决于很多事情(比如你是否想要使用模板,因为实现需要在头文件中公开,是否要处理每个实例化的不同类型...),但是你'正确地重新实现设计。
通常,实现一个什么都不做的函数是坏事,因为接口说的是完全不同的东西(subCalculate而不是doNothing),但是在策略的情况下,策略名称清楚地表明函数不会做任何事情。否则我需要做类型特征,比如enable_if等,只是为了排除单个函数调用。
您可能需要仔细考虑您的函数名称... do_any_necessary_calculations()
,ensure_exclusivity()
而不是lock_mutex()
,after_each_value()
而不是print_breaks
等。< / p>