对不可行的函数模板进行类型推导

时间:2014-03-10 12:51:14

标签: c++ templates overload-resolution argument-deduction

his answerthis question和评论部分,Johannes Schaub说当尝试为需要更多参数的函数模板执行模板类型推导时,存在“匹配错误”通过:

template<class T>
void foo(T, int);

foo(42); // the template specialization foo<int>(int, int) is not viable

在另一个问题的上下文中,相关的是函数模板的类型推导是否成功(并且替换发生):

template<class T>
struct has_no_nested_type {};

// I think you need some specialization for which the following class template
// `non_immediate_context` can be instantiated, otherwise the program is
// ill-formed, NDR
template<>
struct has_no_nested_type<double>
{ using type = double; };

// make the error appear NOT in the immediate context
template<class T>
struct non_immediate_context
{
    using type = typename has_no_nested_type<T>::type;
};


template<class T>
typename non_immediate_context<T>::type
foo(T, int) { return {}; }

template<class T>
bool foo(T) { return {}; }


int main()
{
    foo(42);      // well-formed? clang++3.5 and g++4.8.2 accept it
    foo<int>(42); // well-formed? clang++3.5 accepts it, but not g++4.8.2
}

在为foo实例化第一个函数模板T == int时,替换产生的无效类型不在foo的直接上下文中。这导致了一个严重的错误(这就是the related question的意思。)

但是,当让foo推断出它的模板参数时,g ++和clang ++同意不进行实例化。作为Johannes Schaub explains,这是因为存在“匹配错误”。

问题:什么是“匹配错误”,以及在标准中指定的位置和方式?

替代问题:为什么g ++的foo(42)foo<int>(42)之间存在差异?


到目前为止我发现/尝试的内容:

[over.match.funcs] / 7和[temp.over]似乎描述了函数模板的重载决策细节。后者似乎要求替换foo的模板参数。

有趣的是,[over.match.funcs] / 7在检查函数模板的可行性(特化)之前触发[temp.over] 中描述的过程。 类似地,类型推导不会考虑默认函数参数(除了使它们成为非推导的上下文之外)。据我所知,似乎并不关心可行性。

另一个可能重要的方面是如何指定类型推导。它作用于单个函数参数,但我看不出包含/依赖于模板参数(如T const&)的参数类型与不包含模板参数的参数类型之间的区别(如int )。

然而,g ++在明确指定模板参数(硬错误)和推断它们(扣除失败/ SFINAE)之间有所不同。为什么呢?

1 个答案:

答案 0 :(得分:2)

我总结的是14.8.2.1p1

中描述的过程
  

模板参数推导是通过将每个函数模板参数类型(称之为P)与调用的相应参数的类型(称之为A)进行比较来完成的,如下所述。

在我们的情况下,我们有P (T, int),而对于A,我们有(int)。对于Tint的第一对P / A,我们可以将Tint匹配(通过14.8.2.5中描述的过程)。但对于第二个“对”,我们有int但没有对应物。因此,不能对这个“对”进行推论。

因此,通过14.8.2.5p2,“如果不能对任何P / A对进行类型推导,...,模板 论证推论失败。“。

然后,您将永远不会将模板参数替换为函数模板。

这一切都可以在标准(IMO)中更准确地描述,但我相信这是人们如何能够实现与Clang和GCC的实际行为相匹配的东西,而且它似乎是对Standardese的合理解释。