【问题标题】:C++ function vs template with an integer parameter?C ++函数与带有整数参数的模板?
【发布时间】:2013-02-13 01:04:32
【问题描述】:

阅读维基百科Optimizing C++,在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;
     }
}

还是完全没有必要?你能解释一下原因吗?

【问题讨论】:

  • 如果编译器在编译时就知道“param”的值,它可能会完全去掉这个开关,只保留可以到达的代码。
  • 不是很有用。如果它一个常量,你让编译器内联代码,我猜结果会是一样的。
  • 你提到的那个页面上已经给出了原因。如果整数值在应用程序代码中是常量,但在库代码中是变量,则将其设为模板参数。

标签: c++ function templates


【解决方案1】:

只有在编译时知道参数时,您想到的调整才有效。在您的报价中,有一个关于您在编写库时无法做出的应用程序代码的假设。

如果你的函数调用在应用程序代码中曾经是

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_*()调用if 参数是常量。

请注意,这两个选项都需要将函数的定义暴露给应用程序的代码。我更喜欢使用第二个选项。

【讨论】:

  • 模板和内联函数都需要暴露函数定义(除非你敢进入现在已弃用且从未真正支持的 C++03 导出模板的地下城)
  • 这就是我在上一句中所说的(注意“也”)。我会重写一下。
【解决方案2】:

这取决于您希望如何使用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

当您可以在编译时提供在运行时不会更改的参数时,您可以使用模板。模板总是在编译时进行评估,因此它们的输入和输出在程序运行之前是固定的

如果您知道有人可以提前修复输入并期望某些功能输出,请制作模板版本。否则,常规函数运行时版本就可以了。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-27
      • 2019-10-20
      • 2020-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多