关于推导转换函数模板参数的几个问题

jac*_*k X 6 c++ templates language-lawyer

推导转换函数模板的模板参数的规则位于temp.deduct.conv部分。

第一条规则指定对应的P和A是什么,第一个问题在这里:

模板参数推导是通过将转换函数模板的返回类型(称为 P)与正在查找的转换函数 id 的转换类型 id 指定的类型(称为 A)进行比较来完成的,如 [温度扣除类型]。如果 conversion-function-id 是在重载决策 ([over.match.funcs]) 期间构造的,则应用以下转换。

#include <iostream>
struct C{
    template<typename Type>
    operator Type(){
        Type a{};
        /*a = 1;*/
        return a;
    }
};

int main(){
    int const& rf = C{};
}
Run Code Online (Sandbox Code Playgroud)

对于这个例子,P 应该是,Type但是 A 是什么?似乎只有一条规则与之相关:
over#match.funcs.general-7

在考虑类 S 的转换函数来初始化类型 T 的对象或引用的每种情况下,候选函数包括在 S 中搜索转换函数 ID 运算符 T的结果。

我不知道 A 是否仅存在int const&于此,或者是否是为此初始化定义的任何允许的类型。

如果 A 由前者决定,则 P 为Type且 A 为int const&

根据第 2 条:

如果 P 是引用类型,则使用 P 引用的类型代替 P 进行类型推导以及本子条款其余部分中对 P 的任何进一步引用或转换。

因此,变换后的 P 仍然是Type,那么这样的 P/A 对将经历项目符号 3

如果 A 不是引用类型:

  • [...]

因为 A 是引用类型,所以跳过第 3 点。继续第 4 点

如果 A 是 cv 限定类型,则类型推导将忽略 A 类型的顶级 cv 限定符。如果A是引用类型,则使用A引用的类型进行类型推导。

经过第 4 条,现在 A 转变为int const

第 5 条说:

一般来说,推导过程尝试找到模板参数值,使推导的 A与 A相同。但是,A 的某些属性可能会被忽略:

  • 如果原始 A 是引用类型,则 A 的任何 cv 限定符(即引用引用的类型)。
  • 如果原始 A 是函数指针或成员函数指针类型,则其为 noexcept。
  • A 中可以通过限定转换恢复的任何 cv 限定符。

仅当类型推导失败时才会忽略这些属性。

这里有一个问题,编译器说推导的 A 是int,但是 IIUC 推导Typeconst int,推导的类型不是const int吗?为什么推导的模板参数是int而不是const int

如果将转换函数模板更改为

#include <iostream>
struct C{
    template<typename Type>
    operator Type&(){
        static Type a{};
        a = 1;
        return a;
    }
};

int main(){
    int const& rf = C{};
}
Run Code Online (Sandbox Code Playgroud)

则将Type推导为const int. 为什么此时推导出来的类型与上面的例子不一样呢?(它们应该是相同的结果,即const int)。Type在第一个示例中,我错过了从“const int”推导的任何内容吗?