为什么要使用非类型模板参数

为什么要使用非类型模板参数

本文介绍了为什么要使用非类型模板参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了许多问题和答案,但是此问题最吸引我的目光;它及其答案很有帮助,但我仍然觉得我不完全了解使用非类型模板参数的用途和理论.它们提供了许多有关何时使用它的有用示例,但没有一个真正揭示非类型模板参数背后的理论.

I have read many questions and answers, but this question caught my eye the most; it and its answers are helpful but I still feel that I do not fully understand the uses and the theories behind using non-type template arguments. They provide many useful examples as to when it is used, but none really shed light on the theories behind the non-type template arguments.

我有兴趣不专门了解示例中的时间,而更广泛地了解为什么我倾向于仅在常规函数参数上使用非类型模板参数.

I am interested in knowing not specifically when in examples, but more broadly why I would be inclined to use a non-type template argument over just a regular function argument.

我知道它们是在编译时确定的,并且每个新调用都会使用确定的非类型模板参数值创建一个新函数.因此,当我只想将我想要的参数输入到一个函数中并得到相同的结果(据推测只是一个编译函数)时,为什么还要创建同一函数的许多不同实例呢?

I understand that they are determined at compile-time and that every new call creates a new function with the determined value for the non-type template argument. So why exactly would I want to create many different instances of the same function when I could just input the parameter I want into a function and have the same result - supposedly - with only one compiled function.

本质上,根据的="nofollow noreferrer"> cplusplus.com ?

In essence, why should I be inclined to do #1, instead of #2, as according to the final section of this page of cplusplus.com?

#1:

template <class T, int N>
T fixed_multiply (T val)
{
  return val * N;
}

int main() {
  std::cout << fixed_multiply<int,2>(10) << '\n';
  std::cout << fixed_multiply<int,3>(10) << '\n';
}

#2:

template <class T>
T fixed_multiply (T val, int N)
{
  return val * N;
}

int main() {
  std::cout << fixed_multiply<int>(10, 2) << '\n';
  std::cout << fixed_multiply<int>(10, 3) << '\n';
}

此外,是否会有任何性能优势或两者中的任何一项?是否有任何普通的应用程序可以从使用非类型模板参数中受益,或者这是特定应用程序中用来产生特定结果的技术含量很高的参数?

In addition, would there be any performance benefits or the such of either one? Are there any common applications that could benefit from using non-type template arguments, or is this a highly technical parameter used in specific applications to yield specific results?

由于某种原因,它被标记为重复项,第一段解释了我提出类似问题的原因.

This got marked as a duplicate for some reason, the first paragraph explains my reasons for a similar question.

推荐答案

当您希望(或需要)编译器进行某些编译时优化,同时保持良好的代码构造时,它们很有用.我将简要列出一些示例:

They are useful when you want (or need) the compiler to make certain compile-time optimizations while keeping code well-factored. I'll briefly list a few examples:

消除分支

void doSomething(bool flag) {
  if (flag) {
    //whatever
  }
}

template <bool flag>
void doSomething() {
 if (flag) {
   //whatever
}

}

在上面的示例中,如果在调用doSomething时始终在编译时知道flag的值,则无需手动创建doSomethingTruedoSomethingFalse函数就可以避免分支的开销要求您重复很多代码.例如,当您要在网络代码中的发送端和接收端之间分解代码时,并且您的代码位于对性能至关重要的堆栈中时,此技巧很有用.

In the above example, if you always know the value of flag at compile time when you call doSomething, then you can avoid the cost of a branch without manually creating doSomethingTrue and doSomethingFalse functions which may require you to repeat a lot of code. This trick is useful when you want to factor code between send and recv sides in network code, for example, and your code sits deep down in a performance-critical stack.

避免动态内存管理

void someFunction(size_t size, float* inout) {
  std::vector<float> tmp(size);
  //do something with inout and tmp and then store result in inout
}

template <size_t N>
void someFunction(float *inout) {
  float tmp[N]; //or std::array if you like
  //do something with inout and tmp and store result in inout
}

在上面的示例中,如果第二个版本陷入严重循环中,它的性能会更好.

In the above example, the second version will perform much better if it is stuck inside a critical loop.

允许特殊优化

考虑循环:

for (size_t i = 0; i < N; ++i) {
  //some arithmetic
}

如果编译器知道N为4或8,则可以用等效的SIMD指令替换您的算术,或者至少比N为运行时参数时更智能地展开循环.这种事情在GPU编程(CUDA)世界中很普遍.

If the compiler knows that N is 4 or 8, it may be able to replace your arithmetic with equivalent SIMD instructions, or at least unroll your loop more intelligently than it could if N were a runtime argument. This sort of thing is commonplace in the GPU programming (CUDA) world.

模板元编程

使用模板进行一些非平凡的代码生成时,有时您必须在编译时遍历所有内容.您需要模板非类型参数才能执行此操作.争论包和std::tuple是一种常见的情况,但是还有很多,在这里很难举例说明.

When you do some non-trivial code generation with templates, sometimes you must iterate over things at compile time. You need template non-type arguments to be able to do this. Argument packs and std::tuple are one common case, but there are many more, and hard to exemplify here.

要回答有关何时可以选择模板参数的问题:带有动态(运行时)参数的代码总是更灵活,因此,您只能将某些东西转换为模板参数.通过大幅提高性能来证明其合理性.另一方面,如果您发现自己在一组枚举中编写了很多重复的代码,则应该尝试使用模板进行分解.

To answer your question of when you'd make something a template parameter if you have a choice: code that takes dynamic (runtime) arguments is always more flexible, so you should only convert something to be a template argument if you can justify it with a substantial gain in performance. On the other hand if you find yourself writing much duplicated code over a set of enumerations, you should probably try and factor with templates.

这篇关于为什么要使用非类型模板参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 01:40