c++ - 不可行函数模板的类型推导

标签 c++ templates overload-resolution template-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 ,这是因为存在“匹配错误”。

问题:什么是“匹配错误”,它在标准中的何处以及如何规定?

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


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

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

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

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

然而,g++ 在显式指定模板参数(硬错误)和推导它们(推导失败/SFINAE)之间做出了区分。为什么?

最佳答案

我总结的是14.8.2.1p1描述的流程

Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below.

在我们的例子中,对于 P,我们有 (T, int),对于 A,我们有 (int)。对于第一对 P/A,即 Tint,我们可以将 T 匹配到 int(通过 14.8.2.5 中描述的过程)。但是对于第二个“对”,我们有 int 但没有对应物。因此不能对这个“对”进行扣除。

因此,根据 14.8.2.5p2,“如果无法对任何 P/A 对进行类型推导,...,模板 参数推导失败。”。

这样一来,您就再也不会将模板参数替换到函数模板中了。

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

关于c++ - 不可行函数模板的类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22300620/

相关文章:

c++ - 为什么我可以阻止基元的隐式转换而不是用户定义的类型?

c++ - 如果你有两个同名函数(重载),并且有一个转换构造函数,转换构造函数会被调用吗?

arrays - Delphi如何解析带有指针(无类型)参数的重载函数?

c++ - 在搜索算法上获得微秒输出

C++ 和类型特征 : simplest way of defining a list of possible definitions

c++ - 在类内部和外部定义的模板类的成员函数之间的区别

c++ - 将模板类作为参数传递给方法

c++ - 嵌套模板参数

python - 尽管初始大小固定,但跟踪对象的 BoundingBox/ROI 的大小不断增加

html - perl 子程序输出附加 "1"