11

以下は正常に動作します(予想どおり):

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たり、記述したりすると、GCC も満足します。&X<int> const &x = a

const &そのため、ターゲット タイプがテンプレート クラスでありconst &、そのクラスの非オブジェクトへの変換を要求した場合にのみ、GCC は変換関数を見つけることができません。これは正しい動作ですか?私は標準を読もうとしましたが、オーバーロードの規則は私にとって非常に混乱しています。

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 に従って、コンパイラは次のことを行う必要があります。

  • Pdefine 、変換関数テンプレートの戻り値の型 as 、X<T> const &およびA、必要な結果の型 as X<int>;
  • から参照をP取り除きX<T> constます。
  • から cv-qualification を取り除きP、 を与えX<T>ます。
  • として推測Tintます。

その DR を参照して、 https://gcc.gnu.org/bugzilla/にバグ レポートを提出することをお勧めします。


あなたのケースではクラス型に変換しているため、利用可能な回避策があります。

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

直接初期化では、宛先タイプのコンストラクターが考慮されます (8.5p16)。のデフォルトのコピー コンストラクターはX<int>type のパラメーターを受け取りX<int> const&ますa

于 2014-06-30T17:06:16.187 に答える