以下2段代码有什么区别:
1:
template<size_t min, size_t max>
bool byLength(const std::string& v)
{
return v.length() >= min && v.length() <= max;
}
2:
bool byLength(const std::string& v, size_t min, size_t max)
{
return v.length() >= min && v.length() <= max;
}
使用模板参数而不是函数参数的主要用例是什么?为什么不只是使用第二个例子?
以下2段代码有什么区别?
模板参数必须是常量,在编译时指定。函数参数是变量,不必在编译时知道。
为了说明,使用模板:
byLength<5,10>(v); // OK
size_t min,max;
std::cin >> min >> max;
byLength<min,max>(v); // ERROR: must be constants
而使用函数参数:
byLength(v, 5, 10); // OK
size_t min,max;
std::cin >> min >> max;
byLength(v, min, max); // OK
使用模板参数而不是函数参数的主要用例是什么?
作为常量,它们可以提供更好的优化,并且可以在仅允许常量的情况下(例如数组的大小)使用。
为什么不只是使用第二个例子?
在这种情况下,为什么不呢?这样会更灵活,因为您可以在运行时计算参数,或者从程序的输入中获取它们。如果它是内联的,那么当使用常量值调用时,它应该与模板一样高效。
最大的区别在于你可以用这两个功能做什么:
- 模板函数将其两个限制作为模板的参数,这意味着它们必须在编译时知道
- 常规函数将其两个限制作为常规参数,这意味着您可以使用变量。
基本上,第二个功能可以让你这样做
int a, b;
cout << "Please enter two limits: ";
cin >> a >> b;
string s("quick brown fox");
bool res = byLength(s, a, b);
使用模板功能无法做到这一点:
int a, b;
cout << "Please enter two limits: ";
cin >> a >> b;
string s("quick brown fox");
bool res = byLength<a,b>(s); // <<== DOES NOT COMPILE.
如果所有调用都使用限制参数的常量表达式,则模板函数可以让您节省一些额外的CPU周期,因为编译器可以更好地进行优化。很难想象这些额外周期会产生有意义的差异的情况。
为什么不只是使用第二个例子?
在某些情况下,您需要在函数中使用编译时常量。例如,如果您想申报 std::array<len>
根据其中一个参数,它需要作为模板参数传递,而不是作为常规参数传递:
template<size_t sz>
void demo() {
std::array<sz> data;
...
}
同样不适用于常规函数参数:
void demo(size_t sz) {
std::array<sz> data; // <<== DOES NOT COMPILE.
...
}
您不能使用不是的值调用模板 consexpr
。
最简单的例子是这样的:
1可以使用此代码调用:
const auto Min = numeric_limits<int>::min();
const auto Max = numeric_limits<int>::max();
byLength<Min, Max>(string());
您必须使用2表示仅在运行时已知的值:
cin >> Min >> Max;
// Cannot call by byLength<Min, Max>(string()); because the values are not constexpr
byLength(string(), Min, Max);