带默认参数的模板是C++中的强大泛化编程机制。
问题的历史:
STL库的起始就是从模板开始的。后来可以为模板函数和类的参数指定默认值,以使模板更加通用并保持代码的可扩展性。
问题:
当存在常规函数和模板函数的重载时,可能会出现不明显的冲突,以及在特化时的模糊性。模板中的默认参数可以提高灵活性,但通常导致复杂的编译错误。
解决方案:
最好最小化模板中默认值的数量,特别是在与非模板版本交叉的情况下。函数调用的优先级更喜欢与常规函数的精确匹配,而不是模板。
示例代码:
template<typename T = int> T multiply(T a, T b = T(2)) { return a * b; } int multiply(int a, int b) { return a + b; }
调用 multiply(5, 4) 会选择函数 int multiply(int, int),而调用 multiply<>(5) 将调用模板,b 将接受值2。
关键特性:
可以在模板函数的下一个定义中声明默认参数吗?
不可以,默认值只能在一个地方指定(通常在声明中),否则会出现编译错误。
在模板和非模板函数之间存在不明确性时会发生什么?编译器如何选择调用哪个?
如果准确匹配,编译器将始终优先选择非模板函数。仅在没有精确匹配的情况下,模板才会被调用。
可以为模板参数的非类型参数(例如数字)指定默认值吗?
可以,例如:
template<typename T, int N = 8> class Array { T data[N]; };
负面案例
声明了模板函数和非模板函数,具有相同的参数和默认值。在一个模块中调用正常工作,而在另一个模块中意外选择了错误的函数版本。
优点:
缺点:
正面案例
对于交叉配置,模板和非模板函数声明了明确不同的名称,只有一个版本具有默认值。
优点:
缺点: