c++ - 模板转换函数到 const-reference

标签 c++ gcc clang gcc4.9

以下工作正常(正如人们所期望的那样):

struct X {};

struct A
{
  operator X const& () 
  {
    static const X value{};
    return value; 
  }
};

int main()
{
  A a;
  X x = a;
}

但这还不是很清楚:

template<typename T>
struct X {};

struct A
{
  template<typename T>
  operator X<T> const& () 
  {
    static const X<T> value{};
    return value; 
  }
};

int main() 
{
  A a;
  X<int> x = a;
}

GCC 4.9 说 error: conversion from ‘A’ to non-scalar type ‘X<int>’ requested而 clang 3.4 没有问题。 如果删除 const&从转换函数或者如果你写 X<int> const &x = a那么 GCC 也很高兴。

所以 GCC 只有在目标类型是 const & 时才会找不到转换函数到模板类,您请求转换为非 const &该类的对象。这是正确的行为吗?我试图阅读标准,但重载规则让我很困惑。

最佳答案

是的,这是 gcc 中的错误。这几乎就是 core DR976 ,唯一的区别是在他们的示例中目标类型是非类类型:

struct F {
   template<class T>
   operator const T&() { static T t; return t; }
};

int main() {
   F f;
   int i = f;   // ill-formed
}

与您的示例一样,clang 接受而 gcc 拒绝此示例,无论选择的标准版本方言如何。

请注意,该 DR (14.8.2.3 [temp.deduct.conv]) 修改的条款不区分类别和非类别目标类型,因此该 DR 的决议适用于你的代码同样。

根据修订后的条款 14.8.2.3,编译器应该:

  • 确定P ,转换函数模板的返回类型,为X<T> const & , 和 A , 所需的结果类型,如 X<int> ;
  • P 中删除引用, 给出 X<T> const ;
  • P 中去除 cv 限定条件, 给出 X<T> ;
  • 推断T作为int .

我建议在 https://gcc.gnu.org/bugzilla/ 上提交错误报告引用该 DR。


因为在您的情况下您正在转换为类类型,所以有一个可用的解决方法:

X<int> x1 = a;          // fails
X<int> x2(a);           // OK
X<int> x3 = X<int>(a);  // also OK

在直接初始化中,考虑目标类型的构造函数(8.5p16); X<int> 的默认拷贝构造函数采用 X<int> const& 类型的参数,正如我们已经看到的那样,gcc 很乐意将 a 转换为.

关于c++ - 模板转换函数到 const-reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24491919/

相关文章:

c++ - 具有三元运算符的函数类型

c - clang 中是否有 'Integral constant overflow' 警告?

c++ - 有没有办法用 clang 在 VisitCallExpr 方法中获取 CallExpr* 的调用者?

c++ - 从 sockaddr * 转换为 sockaddr_in * 增加了所需的对齐方式

c++ - 多重继承 : using a member function of a private base

c++ - 从 Boost 进程间共享内存中检索共享 vector

c++ - 列表框属性值未出现在 C++ 自定义操作 Wix 中?

c++ - 整数常量上的错误后缀 Ui64 无效

c++ - 用户是否需要满足任何先决条件才能运行 C++17 软件?

linux - 在没有 liblttng-ust-cyg-profile 的情况下获取 lttng 回溯