在Optimizing C++中阅读Wikibook this paragraph,有以下建议:
如果整数值在应用程序代码中是常量,但在库代码中是变量,则将其设为模板参数。
所以,如果我有像
这样的功能void myfunction(int param)
{
switch(param)
{
case 1:
do_something_1();
break;
case 2:
do_something_2();
break;
...
case 100: // 100 is taken as example
do_something_100();
break;
}
}
方便用以下内容替换它吗?
template<int param> void myfunction()
{
switch(param)
{
case 1:
do_something_1();
break;
case 2:
do_something_2();
break;
...
case 100: // 100 is taken as example
do_something_100();
break;
}
}
或完全没必要?你能告诉我原因吗?
答案 0 :(得分:6)
只有在编译时知道参数时,您才会想到这一点。在您的引用中,有一个关于编写库时无法进行的应用程序代码的假设。
如果您的函数调用过去的应用程序代码
const int x = 3;
myfunction(1);
myfunction(2);
myfunction(x);
//etc...
可以按如下方式重写它们。
const int x = 3;
myfunction<1>();
myfunction<2>();
myfunction<x>();
//etc...
但如果x
是变量,则不可能:
int x = ...; // unknown at compile-time!
myfunction<x>(); // will fail to compile!
如上所述,在某些情况下,您在编写库时不应对应用程序进行假设。有时您想要或需要做。让我们考虑一下你期望应用程序使用常量的情况,但你不想强制它这样做。
您希望优化,因为它将使用常量,但仍允许使用变量。为此,我建议两个选择:
制作两个选择,一个带有模板参数,另一个带有功能参数。
内联该函数,因此在编译应用程序代码时,编译器会看到函数的定义,并可用于将其优化为单个do_something_*()
调用如果参数是常数。
请注意,这两个选项都需要将函数的定义暴露给应用程序的代码。我更喜欢使用第二种选择。
答案 1 :(得分:3)
这取决于您希望如何使用myfunction
。例如,模板化函数不能与运行时声明的变量一起使用:
int dosomethingmaybe = 1;
dosomethingmaybe += 2;
myfunction< dosomethingmaybe >(); // <--- Error, you cannot instantiate a template with a non-constant variable
myfunction( dosomethingmaybe ); // <--- Will call `do_something_3();`, according to your code
如果可以在运行时提供不会更改的参数在编译时,则可以使用模板。模板总是在编译时进行评估,因此在程序运行之前它们的 输入和输出是固定的 !
如果您知道某人可以修复输入并提前获得某些功能输出,请创建模板版本。否则,常规函数运行时版本就可以了。
答案 2 :(得分:1)
我怀疑你在这里的实际情况中确实会看到性能优势。如果内联调用,则两种方法之间没有区别 - 只要参数在编译时已知(它必须是),一个不错的编译器将在两种情况下删除不必要的开关。你会看到差异的唯一情况是如果没有发生内联 - 在这种情况下,模板化方法将允许切换被移除,而另一个则不会。但是,无论如何,函数调用开销可能会使交换机的成本相形见绌。