为什么接下来的两个模板声明不明确(因此两者都不比另一个更专业)?我知道这个问题在 Stack Overflow 上已经被多次提出,但通常人们会回答如何解决歧义,而不是回答为什么会发生这种情况。
I.
template <class T> void func(char* buf, T size) {}
II.
template <std::size_t N> void func(char (&buf)[N], std::size_t size) {}
尝试通过 C++14 标准的步骤来解决部分函数模板排序 (14.5.6.2):
为每个类型、非类型或模板模板参数(包括
模板参数包(其中的14.5.3))分别合成唯一的类型、值或类模板
并将其替换为模板函数类型中该参数的每次出现。
转换后的函数IN模板函数类型为:void func(char*, U1)
, where U1
是一些独特的合成类型。
转换后的函数IN模板函数类型为:void func(char (&buf)[N1], std::size_t)
, where N1
是一些独特的综合价值。
使用转换后的函数模板的函数类型,对另一个模板执行类型推导
如 14.8.2.4 中所述。
因此,让我们尝试在一侧(使用第一个模板作为参数,第二个模板作为参数模板)和相反的一侧执行类型推导。
Case 1.
参数模板:template <std::size_t N> void func(char (&buf)[N], std::size_t size)
。
转换后的参数模板:void func(char*, U1)
.
尝试推断模板参数。 ”char (&buf)[N]
“不能从”推断出char*
" 类型。U1 不匹配std::size_t
键入任一。失败的。
Case 2.
参数模板:template <class T> void func(char* buf, T size)
。
转换后的参数模板:void func(char (&buf)[N1], std::size_t)
.
尝试推断模板参数。参数模板的第一个参数根本不是类型,它与char[]
. T
应推论为std::size_t
.
所以模板II应该更专业一些,应该在下面的代码中选择:
char buf[16];
func(buf, static_cast<std::size_t>(16));
为什么 GCC 5.3 和 Clang 4.0 不是这样?