C ++函数vs带有整数参数的模板?

时间:2013-02-27 09:27:23

标签: c++ function templates

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;
     }
}

或完全没必要?你能告诉我原因吗?

3 个答案:

答案 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)

我怀疑你在这里的实际情况中确实会看到性能优势。如果内联调用,则两种方法之间没有区别 - 只要参数在编译时已知(它必须是),一个不错的编译器将在两种情况下删除不必要的开关。你会看到差异的唯一情况是如果没有发生内联 - 在这种情况下,模板化方法将允许切换被移除,而另一个则不会。但是,无论如何,函数调用开销可能会使交换机的成本相形见绌。