在C++中,您可以使用非类型模板参数创建模板,如下所示:
template< int I >
void add( int& value )
{
value += I;
}
int main( int argc, char** argv )
{
int i = 10;
add< 5 >( i );
std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
其中打印"15"到cout.有什么用?是否有任何理由使用非类型模板参数而不是更常规的类似参数:
void add( int& value, int amount )
{
value += amount;
}
Run Code Online (Sandbox Code Playgroud)
对不起,如果已经被问过(我看了但找不到任何东西).
tem*_*def 23
非类型模板参数有很多应用程序; 这里有几个:
您可以使用非类型参数来实现表示固定大小的数组或矩阵的泛型类型.例如,您可以Matrix在其维度上参数化类型,因此您可以创建一个Matrix<4, 3>或一个Matrix<2, 2>.如果然后正确定义这些类型的重载运算符,则可以防止意外错误添加或乘以不正确维度的矩阵,并且可以使函数明确地传达它们接受的矩阵的预期维度.这可以通过在编译时检测违规来防止发生大量的运行时错误.
您可以使用非类型参数通过模板元编程实现编译时功能评估.例如,这是一个在编译时计算阶乘的简单模板:
template <unsigned n> struct Factorial {
enum {
result = n * Factorial<n - 1>::result
};
};
template <> struct Factorial<0> {
enum {
result = 1
};
};
Run Code Online (Sandbox Code Playgroud)
这允许您编写代码Factorial<10>::result,以便在编译时获取10!的值.这可以防止在运行时执行额外的代码.
此外,您可以使用非类型参数来实现编译时维度分析,这允许您定义千克,米,秒等类型,以便编译器可以确保您不会意外地使用公斤表示米等
希望这可以帮助!
在这种情况下你可能是对的,但有些情况下你需要在编译时知道这些信息:
但是这个怎么样?
template <std::size_t N>
std::array<int, N> get_array() { ... }
Run Code Online (Sandbox Code Playgroud)
std::array 需要在编译时知道它的大小(因为它是在堆栈上分配的).
你做不到这样的事情:
std::array<int>(5);
Run Code Online (Sandbox Code Playgroud)
在那个特定的例子中,没有任何优势.但是,使用模板参数一样,你可以做很多事情你不能做,否则,如有效结合变量函数(如boost::bind),指定一个函数或类编译时数组的大小(std::array是一个现成的例子那个)等等
例如,使用该函数,您可以编写类似的函数
template<typename T>
void apply(T f) {
f(somenum);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以传递apply一个函数:
apply(&add<23>);
Run Code Online (Sandbox Code Playgroud)
这是一个非常简单的例子,但它证明了这个原理.更高级的应用程序包括将函数应用于集合中的每个值,计算诸如编译时函数的阶乘等内容.
你不能以任何其他方式做任何事情.
嗯,这是编译时多态和运行时多态之间的典型选择.
从您的问题的措辞中可以看出,您在"普通"模板参数中看不到任何异常,同时将非类型参数视为奇怪和/或冗余.实际上,同样的问题也可以应用于模板类型参数(您称之为"普通"参数).相同的功能通常可以通过具有虚函数的多态类(运行时多态)或通过模板类型参数(编译时多态)来实现.我们也可以问为什么我们需要模板类型参数,因为几乎所有东西都可以使用多态类来实现.
如果是非类型参数,您可能希望有一天会有这样的事情
template <int N> void foo(char (&array)[N]) {
...
}
Run Code Online (Sandbox Code Playgroud)
无法使用运行时值实现.