在重载解析期间对转换序列进行排序时,数组到指针的转换被视为完全匹配(C++11 13.3.3.1.1/1 表 12)。与您的直觉相反,这意味着 (3) 和 (5) 同样适合A<5> a("0123456789");
。领带断了 - 作为Xeo 在他的评论中说 https://stackoverflow.com/questions/23291042/how-to-disambiguate-this-template#comment35652352_23291042- 赞成非模板(3)。您可能会想通过将 (3) 也转换为模板来欺骗编译器:
template <typename=void>
A(const char * const) : b{} {}
但这样做会只会导致结构的歧义 http://ideone.com/2kNmWx。确实没有简单的方法可以消除歧义const char (&)[]
and const char*
重载:最好的解决方案可能是更改 (3) 以接受指针和长度:
A(const char * const, std::size_t) : b{} {
std::cout << "size: " << SIZE << " ctor 3\n";
}
顺便说一句,我会注意到添加size_t
论证const char* const
构造函数也消除歧义A("five") case http://ideone.com/SLtms6.
编辑:但是,一种消除歧义的合理方法char*来自数组构造函数的构造函数 http://ideone.com/LUGs60,通过引用接受指针参数:
template <typename T,
typename=typename std::enable_if<
std::is_same<typename std::remove_cv<T>::type, char>{}
>::type>
A(T* const&) : b{} { std::cout << "size: " << SIZE << " ctor 3\n"; }
[这个特殊技巧的功劳在于dyp https://stackoverflow.com/questions/23291042/how-to-disambiguate-this-template/23295859?noredirect=1#comment35669703_23295859,可能还有 Johannes Schaub 或 Yakk 或我(我很确定那不是我)。]
该模板通过引用有效地锁定实际类型(在发生数组到指针转换之前),然后限制对非指针类型的引用。