C++ - 转换函数模板演绎,为什么这个工作?

Cae*_*sar 8 c++ templates type-conversion implicit-conversion

class A
{
    struct B{};
public:
    static void test(A::B){}
};

struct C
{
    template<class T>
    operator T()
    {
        return T();
    }
};

int main()
{
    A::test(C());
}
Run Code Online (Sandbox Code Playgroud)

此代码适用于clang 3.7,gcc 5.1和vc ++ 14.2.
2问题,
1.为什么模板推导出的类型是A :: B?(太聪明了!)
据我所知,模板通过return语句而不是参数来推断类型.
但是我发现了一些对N4606 12.3.2感兴趣的东西A conversion function template shall not have a deduced return type (7.1.7.4).(但是,我找不到关于此的更多信息,因为7.1.7.4太难理解了.)
2.为什么转换函数模板可以访问A :: B?

谢谢.

Bar*_*rry 4

  1. 为什么模板可以推导出类型是A::B?(这么聪明!)

由于test()需要 an A::B,您需要一种将 a 转换C为 an 的方法A::B。我们可以尝试通过转换函数进行初始化,我们在[over.match.conv]中有:

S考虑了 及其基类的转换函数。那些未隐藏在S并产生类型T或可T通过标准转换序列 (13.3.3.1.1) 转换为类型的类型中的非显式转换函数是候选函数。

我们根据[temp.conv]进行模板推导:

模板参数推导是通过将转换函数模板的返回类型(称为 P)与转换​​结果所需的类型(称为 A;参见 8.6、13.3.1.5 和 13.3.1.6)来完成的。确定该类型)如 14.8.2.5 中所述。

基本上,我们将Tin推导template <class T> operator T()A::B。这是一个格式良好的转换序列,也是唯一可行的转换序列,所以这就是发生的情况。

您引用的有关“推导的返回类型”的行引用了autodecltype在返回类型中。这不会发生在这里。

  1. 为什么转换函数模板可以访问A::B?

访问规则严格与名称有关。名称且只有名称是 私有 。但我们不是访问名称而是直接推导类型。BA

B的构造函数是公共的,因此转换函数的主体也是格式良好的,因此有关代码的所有内容都是格式良好的。