fan*_*rin 7 c++ function-templates overload-resolution compiler-bug
我定义了两个版本的函数模板,名为compare:
#include <cstring>\n\nusing namespace std;\n\n// fist version\ntemplate <size_t N, size_t M>\nint compare(const char (&a)[N], const char (&b)[M]) {\n return strcmp(a, b);\n}\n\n// second version\ntemplate <typename T>\nint compare(const T &a, const T &b) {\n if (a < b) return -1;\n if (b < a) return 1;\n return 0;\n}\n\nint main() {\n const char *p1 = "dog", *p2 = "cat";\n compare(p1, p2); // call second version\n compare("dog", "cat"); // call second version?\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n在使用c++11std的CPP Primer(第5版)一书中,作者说compare(p1, p2)将调用第二版模板,因为没有办法将指针转换为对数组的引用。将compare("dog", "cat")调用第二个版本,compare因为它比第一个版本更专业。
但是,当我运行此代码时,出现编译器错误:
\n\n\n重载 \xe2\x80\x98compare(const char [4], const char [4])\xe2\x80\x99 的调用不明确
\n
然后我改成compare("dog", "cat")了compare("dog", "cats"),就可以毫无问题地调用第二个版本模板了。
为什么a和b具有相同的长度会导致歧义?
use*_*570 10
太棒了;这是CWG 2160,它指出当前的措辞没有说明/指定部分排序期间冲突的推导类型是否应该无效或忽略(有效)。MSVC 似乎忽略了由于调用而导致的冲突compare("dog", "cat");并接受程序,而 GCC 和 Clang 似乎拒绝了部分排序过程中冲突的推导类型并拒绝了程序。
版本 1 是专门为const char数组编写的。对于所有其他类型,第二个版本是可行的选择。因此,对于第一次调用,应选择compare(p1, p2)第二个版本,因为第一个版本甚至不可行。compare(const T &a, const T &b)compare(const char (&a)[N], const char (&b)[M])
现在进行第二次通话compare("dog", "cat")。这里,在部分排序期间,当将版本 1 的转换模板与原始模板版本 2 进行匹配时,会推导出冲突T类型。现在,当前的措辞并未指定是否应忽略或接受这种冲突行为。MSVC 似乎忽略了冲突的推导类型,而 GCC 和 Clang 似乎拒绝它。这仍然是一个悬而未决的问题。如果冲突类型被忽略,则匹配成功;如果冲突类型不被忽略,则匹配失败。因此,第一种情况有两种可能性。
再次执行相同的过程,即尝试将第二个模板的转换类型与原始模板版本 1 匹配失败。
本质上,根据部分排序期间是否忽略冲突类型,有两种可能性:
compare("dog", "cat")。GCC 拒绝使用const char字符串文字调用更专门的数组版本。