C++ 模板 <unsigned int N> 是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/499106/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:41:22  来源:igfitidea点击:

What does template <unsigned int N> mean?

c++templates

提问by Igor Oks

When declaring a template, I am used to having this kind of code:

在声明模板时,我习惯了这样的代码:

template <class T>

But in this question, they used:

但是在这个问题中,他们使用了:

template <unsigned int N>

I checked that it compiles. But what does it mean? Is it a non-type parameter? And if so, how can we have a template without any type parameter?

我检查它编译。但是这是什么意思?它是非类型参数吗?如果是这样,我们如何拥有一个没有任何类型参数的模板?

回答by Johannes Schaub - litb

Yes, it is a non-type parameter. You can have several kinds of template parameters

是的,它是一个非类型参数。你可以有几种模板参数

  • Type Parameters.
    • Types
    • Templates (only classes and alias templates, no functions or variable templates)
  • Non-type Parameters
    • Pointers
    • References
    • Integral constant expressions
  • 类型参数。
    • 类型
    • 模板(只有类和别名模板,没有函数或变量模板)
  • 非类型参数
    • 指针
    • 参考
    • 积分常数表达式

What you have there is of the last kind. It's a compile time constant (so-called constant expression) and is of type integer or enumeration. After looking it up in the standard, i had to move class templates up into the types section - even though templates are not types. But they are called type-parameters for the purpose of describing those kinds nonetheless. You can have pointers (and also member pointers) and references to objects/functions that have external linkage (those that can be linked to from other object files and whose address is unique in the entire program). Examples:

你所拥有的是最后一种。它是一个编译时常量(所谓的常量表达式)并且是整数或枚举类型。在标准中查找之后,我不得不将类模板移到类型部分 - 即使模板不是类型。但是为了描述这些类型,它们被称为类型参数。您可以拥有指针(以及成员指针)和对具有外部链接的对象/函数的引用(那些可以从其他对象文件链接到并且其地址在整个程序中是唯一的)。例子:

Template type parameter:

模板类型参数:

template<typename T>
struct Container {
    T t;
};

// pass type "long" as argument.
Container<long> test;

Template integer parameter:

模板整数参数:

template<unsigned int S>
struct Vector {
    unsigned char bytes[S];
};

// pass 3 as argument.
Vector<3> test;

Template pointer parameter (passing a pointer to a function)

模板指针参数(传递指向函数的指针)

template<void (*F)()>
struct FunctionWrapper {
    static void call_it() { F(); }
};

// pass address of function do_it as argument.
void do_it() { }
FunctionWrapper<&do_it> test;

Template reference parameter (passing an integer)

模板参考参数(传递一个整数)

template<int &A>
struct SillyExample {
    static void do_it() { A = 10; }
};

// pass flag as argument
int flag;
SillyExample<flag> test;

Template template parameter.

模板模板参数。

template<template<typename T> class AllocatePolicy>
struct Pool {
    void allocate(size_t n) {
        int *p = AllocatePolicy<int>::allocate(n);
    }
};

// pass the template "allocator" as argument. 
template<typename T>
struct allocator { static T * allocate(size_t n) { return 0; } };
Pool<allocator> test;

A template without any parameters is not possible. But a template without any explicit argument is possible - it has default arguments:

没有任何参数的模板是不可能的。但是没有任何显式参数的模板是可能的 - 它具有默认参数:

template<unsigned int SIZE = 3>
struct Vector {
    unsigned char buffer[SIZE];
};

Vector<> test;

Syntactically, template<>is reserved to mark an explicit template specialization, instead of a template without parameters:

在语法上,template<>保留用于标记显式模板特化,而不是没有参数的模板:

template<>
struct Vector<3> {
    // alternative definition for SIZE == 3
};

回答by maxaposteriori

It's perfectly possible to template a class on an integer rather than a type. We can assign the templated value to a variable, or otherwise manipulate it in a way we might with any other integer literal:

完全可以在整数而不是类型上模板化一个类。我们可以将模板化的值分配给一个变量,或者以其他任何整数文字的方式对其进行操作:

unsigned int x = N;

In fact, we can create algorithms which evaluate at compile time (from Wikipedia):

事实上,我们可以创建在编译时进行评估的算法(来自维基百科):

template <int N>
struct Factorial 
{
     enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
    int x = Factorial<4>::value; // == 24
    int y = Factorial<0>::value; // == 1
}

回答by Martin York

You templatize your class based on an 'unsigned int'.

您根据“无符号整数”对类进行模板化。

Example:

例子:

template <unsigned int N>
class MyArray
{
    public:
    private:
        double    data[N]; // Use N as the size of the array
};

int main()
{
    MyArray<2>     a1;
    MyArray<2>     a2;

    MyArray<4>     b1;

    a1 = a2;  // OK The arrays are the same size.
    a1 = b1;  // FAIL because the size of the array is part of the
              //      template and thus the type, a1 and b1 are different types.
              //      Thus this is a COMPILE time failure.
 }

回答by Jonathan

A template class is like a macro, only a whole lot less evil.

模板类就像一个宏,只是少了很多邪恶。

Think of a template as a macro. The parameters to the template get substituted into a class (or function) definition, when you define a class (or function) using a template.

将模板视为宏。当您使用模板定义类(或函数)时,模板的参数会被替换为类(或函数)定义。

The difference is that the parameters have "types" and values passed are checked during compilation, like parameters to functions. The types valid are your regular C++ types, like int and char. When you instantiate a template class, you pass a value of the type you specified, and in a new copy of the template class definition this value gets substituted in wherever the parameter name was in the original definition. Just like a macro.

不同之处在于参数具有“类型”,并且在编译期间检查传递的值,就像函数的参数一样。有效类型是您的常规 C++ 类型,如 int 和 char。当你实例化一个模板类时,你传递一个你指定类型的值,并且在模板类定义的新副本中,这个值被替换在参数名称在原始定义中的任何地方。就像一个宏。

You can also use the "class" or "typename" types for parameters (they're really the same). With a parameter of one of these types, you may pass a type name instead of a value. Just like before, everywhere the parameter name was in the template class definition, as soon as you create a new instance, becomes whatever type you pass. This is the most common use for a template class; Everybody that knows anything about C++ templates knows how to do this.

您还可以使用 " class" 或 " typename" 类型作为参数(它们实际上是相同的)。使用这些类型之一的参数,您可以传递类型名称而不是值。就像以前一样,参数名称在模板类定义中的任何地方,只要您创建一个新实例,就会成为您传递的任何类型。这是模板类最常见的用途;每个了解 C++ 模板的人都知道如何做到这一点。

Consider this template class example code:

考虑这个模板类示例代码:

#include <cstdio>
template <int I>
class foo
{
  void print()
  {
    printf("%i", I);
  }
};

int main()
{
  foo<26> f;
  f.print();
  return 0;
}

It's functionally the same as this macro-using code:

它在功能上与这个使用宏的代码相同:

#include <cstdio>
#define MAKE_A_FOO(I) class foo_##I \
{ \
  void print() \
  { \
    printf("%i", I); \
  } \
};

MAKE_A_FOO(26)

int main()
{
  foo_26 f;
  f.print();
  return 0;
}

Of course, the template version is a billion times safer and more flexible.

当然,模板版本更安全,更灵活。