【发布时间】:2018-07-03 22:07:49
【问题描述】:
参考this question,它确实具有相同的标题,但我在标准中找到了答案。我继续挖掘这个主题,最后找到了这个答案不适用的示例代码。
让我们考虑这段代码:
template<class T> void func(T* buf); //template I
template<size_t N> void func(char (&buf) [N]); //template II
void g(char (&buf)[3])
{
func(buf) //Error: ambiguous function call (Clang, GCC, ICC, MSVC)
}
根据[temp.func.order] 和[temp.deduct.partial] 中的偏序规则,如果通过执行这段代码:
template <class T> void func1(T* buf) {}
template <std::size_t N> void func2(char (&buf)[N]) {}
struct invented_T{};
constexpr std::size_t invented_N=42;
void is_template_I_more_specialized(invented_T* buf)
{
func2(buf);
//DO NOT COMPILE
// => template I is not more specialized than func2
}
void is_template_II_more_specialized(char (&buf)[invented_N])
{
func1(buf);
//DO COMPILE
// => template II is more specialized than func1
}
所以根据这个解释,模板II应该是更专业的。为什么不是这样?
【问题讨论】:
-
非正式的 C++ 文档来源(cppreference、msvc 文档等)表示在执行部分排序的推导时不考虑隐式转换。我自己找不到任何相关的标准。 (我最初在链接的问题下对此发表了评论,然后将其删除,因为它在那里似乎不相关;但它可能与此处相关)。
-
@n.m.所以调用
func1(buf)也不会编译,所以这两个模板都不会更专业。这是你的主意吗?如果您发布它,那将是我会接受的答案。 -
这些是函数模板,AFAIK 没有函数模板的部分特化之类的东西;相反,在函数调用时,两个候选模板中的每一个都是完全特化的(如果可能的话),产生函数名称的候选 重载,然后重载决策规则是应用,好像根本没有涉及任何模板。这会将问题简化为“为什么
void func(char (&buf)[42])和void func(char *buf)是一个模棱两可的重载对?”我不知道答案。 -
@zwol 你的权利,然后选择最佳可行函数的过程继续进行:这两个函数调用的转换顺序排名相同,然后应用以下规则[over.match.best]:F1和 F2 是函数模板特化,根据 [temp.func.order] 中描述的偏序规则,F1 的函数模板比 F2 的模板更特化,
-
@Oliv 是的,这正是这个想法,但我需要在实际的标准文本中找到它才能绝对确定,
标签: c++ templates language-lawyer partial-ordering