11

The following works fine (as one would expect):

struct X {};

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

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

But this is not so clear:

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 says error: conversion from ‘A’ to non-scalar type ‘X<int>’ requested whereas clang 3.4 has no problems with it. If you remove the const or the & from the conversion function or if you write X<int> const &x = a then GCC is happy, too.

So GCC only fails to find the conversion function if the target type is a const & to a template class and you request a conversion to a non-const & object of that class. Is this the correct behavior? I tried to read the standard but the overloading rules are quite confusing to me.

4

1 回答 1

5

是的,这是 gcc 中的一个错误。这几乎完全是核心 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,转换函数模板的返回类型, as X<T> const &,和A,所需的结果类型, as X<int>
  • 剥离参考P,给予X<T> const
  • P从,中去除 cv 资格X<T>
  • 推断Tint

我建议在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

于 2014-06-30T17:06:16.187 回答