我在教自己' D'我有一些关于模板的问题。例如,我目前正在阅读的文章(请参阅本文的底部)包含以下代码:
int foo(int x)
{
return x;
}
string foo(string x)
{
return x;
}
void main()
{
assert(foo(12345) == 12345);
assert(foo("hello") == "hello");
}
显然,这个特定的片段不够优雅,模板可以消除重复:
foo(T)(T x)
{
return x;
}
void main()
{
assert(foo!(int)(12345) == 12345);
assert(foo!(string)("hello") == "hello");
}
第二个例子是相当基本的,因为我们只是返回传递的值。我的混淆是因为这个函数,无论是模板化的,仍然出现被约束为一种类型的值,因为我不能轻易地设想一个字符串和一个有很多共同点的整数值。因此,程序员是否需要检查传递的变量类型,然后编写代码来分别处理字符串或整数的情况?创建一个真正更高效的大型功能体?我意识到我对模板的不熟悉是显而易见的。因此我的问题是:)
答案 0 :(得分:4)
“模板”的字面定义是“作为其他人复制模型的东西”,这就是编译器的作用。对于每种类型(在您的情况下为字符串和int),它复制模板函数并在编译期间创建专用函数。
在运行时不需要模板,因此可以在编译后丢弃。在已编译的二进制文件中,有两个函数foo!(int)
和foo!(string)
。
程序员是否需要检查传递的变量类型,然后编写代码来分别处理字符串或整数的情况?
这取决于。有时你想这样做。例如,优化性能。有时您不需要这样做并编写通用函数。
创建一个真正更高效的大型功能体吗?
有时。如果没有,那就不要这样做。例如,您可以编写一个通用find
函数,该函数适用于数组,链接列表和类似的东西。
答案 1 :(得分:1)
模板是您希望平等处理的类型的可重用代码。因此,如果你想“分别处理字符串或整数的情况”,它们可能不是正确的工具。
以任意容器为例,其中包含T个元素。即使string和int没有太多共同之处,你也可以为每个人创建一个容器。
另一个例子是数学向量,您可以在其中指定使用的类型。您可以指定数学函数而不必将自己限制为单一类型,并且它们甚至可以使用自定义类型,因为它们已经重载了必要的运算符。