转换运算符的模板参数类型推导

use*_*538 17 c++ templates operator-overloading c++11 type-deduction

我看到C++ 11标准中的例子(n3337,14.8.2.3/7)

struct A {
template <class T> operator T***();
};
A a;
const int * const * const * p1 = a; // T is deduced as int, not const int
Run Code Online (Sandbox Code Playgroud)

并尝试由不同的编译器重现它.我通过在转换函数中添加类型为T的声明来稍微改变了示例

struct A {
    template <class T> operator T***()
    {
        T t;  //if T==const int, then it is error (uninitialized const)
        return nullptr;
    }
};
A a;
const int * const * const * p1 = a;

int main(){}
Run Code Online (Sandbox Code Playgroud)

所有编译器(VS2014,gcc 5.1.0和clang 3.5.1)都在"t"的声明中给出了一个错误,这意味着T被推导为const int.这是为什么?这是一些扩展吗?

Col*_*mbo 9

CWG问题#349涵盖了这个问题,由EDG C++前端开发人员开放(显然是推论int,而不是const int):

在为转换函数执行模板参数推导时,我们遇到了有关资格转换的问题.

问题是:此示例调用的转换函数中的T类型是什么?是T"int"还是"const int"?

如果T是"int",则类A中的转换函数起作用,而类B中的转换函数失败(因为返回表达式无法转换为函数的返回类型).如果T是"const int",则A失败并且B工作.

因为对转换函数的结果执行了限定转换,所以我认为将T推导为const int没有任何好处.

另外,我认为类A中的代码比B类中的代码更容易出现.如果类的作者计划返回指向const实体的指针,我希望该函数是用返回类型中的const.

因此,我认为正确的结果应该是T是int.

struct A {
  template <class T> operator T***() {
      int*** p = 0;
      return p;
  }
};

struct B {
  template <class T> operator T***() {
      const int*** p = 0;
      return p;
  }
};

int main()
{
  A a;
  const int * const * const * p1 = a;
  B b;
  const int * const * const * p2 = b;
}
Run Code Online (Sandbox Code Playgroud)

我们刚刚实施了这个功能,并且在委员会要求澄清之前,我们将T推断为int.似乎g ++和Sun编译器将T推导为const int.

这只引入了引用的段落(它在C++ 03中不存在!),并且可能被编译器开发人员忽略了.