C++迭代器标签函数重载 模板默认实现匹配优先级不符合预期
问题原因
该现象由C++标准的重载决议规则决定,核心误区是对「非模板函数优先级高于模板函数」规则的触发条件理解有误:
该规则仅在两个可行函数的实参到形参转换序列等级完全相同时生效。如果转换序列的优先级有差异,会优先选择转换序列更优的函数,不再比较是否为模板。
你的场景下的可行函数分析
你传入的实参类型是std::bidirectional_iterator_tag,两个可行函数的转换序列等级如下:
- 非模板函数
void test(std::forward_iterator_tag):std::bidirectional_iterator_tag是std::forward_iterator_tag的派生类,需要做一次派生类到基类的转换,转换序列等级为「转换」级。 - 模板实例化得到的
void test<std::bidirectional_iterator_tag>(std::bidirectional_iterator_tag):形参与实参类型完全一致,属于最高优先级的「完全匹配」级。
完全匹配的优先级高于转换级,因此模板实例化的函数直接胜出,最终调用了模板版本。
正确的低优先级兜底实现
你提到的用可变参数...实现兜底的方案是符合标准的,因为...对应的可变参数转换序列是所有转换序列中优先级最低的,修改后代码如下:
#include <iterator> #include <iostream> using namespace std; void test(std::forward_iterator_tag) { cout << "forward_iterator_tag" << endl; } void test(std::random_access_iterator_tag) { cout << "random_access_iterator_tag" << endl; } // 兜底改为可变参数版本,优先级最低 void test(...) { cout << "other tag" << endl; } int main(){ test(bidirectional_iterator_tag{}); // 会输出 forward_iterator_tag,符合预期 return 0; }
内容的提问来源于stack exchange,提问作者Adrian。
相关产品推荐
相关产品推荐

