1

次のコードを検討してください。

#include<iostream>
#include<vector>
using namespace std;
class Foo {
public:
  template< typename T> 
  operator vector< T >() const {
    return vector< T >();
  }

  template< typename T> 
  operator T() const {
    return T();
  }
};

int main () {
  Foo b;
  vector< int >  q = b;
  q = b;
}

次の2つのコマンドのいずれかを使用して、Clangまたはg++でこれをコンパイルします。

g++ test.cpp
clang++ test.cpp

ただし、C ++ 11機能を有効にすると、失敗します。

g++ --std=c++0x test.cpp
clang++ --std=c++11 test.cpp

エラーメッセージは次のようになります。

test.cpp:20:5: error: use of overloaded operator '=' is ambiguous (with operand types 'vector<int>' and 'Foo')
  q = b;
  ~ ^ ~
/usr/include/c++/4.6/bits/stl_vector.h:373:7: note: candidate function
      operator=(vector&& __x)
      ^
/usr/include/c++/4.6/bits/stl_vector.h:362:7: note: candidate function
      operator=(const vector& __x);
      ^
/usr/include/c++/4.6/bits/stl_vector.h:394:7: note: candidate function
      operator=(initializer_list<value_type> __l)
      ^
1 error generated.

C ++ 11がないと機能するのに、C++11がないと機能する理由はわかりません。移動、行に注意してください

vector< int >  q = b; // In the main function, line 19

main関数でエラーが発生することはありません。なぜそれが機能しないのか、そしてそれをC ++ 11で機能させるために何ができるのかを誰かが説明できますか?

4

1 に答える 1

2

ここにはコンパイラのバグはありません。C ++ 11では、変換コンストラクターと代入演算子のオーバーロードが追加されたため、コードはC++11で壊れています。

これは、(テンプレート化された変換を使用して)絶対に何にでも変換する型を作成するときに実行するリスクです。 自分自身をに変換するのと同じくらいFoo幸せです。initializer_list<int>vector<int>

その理由

vector<int> q = b;

Clang3.1で動作しますが

vector<int> q(b);

失敗するのは、最初はコピー初期化であり、これには暗黙の変換が必要であり、vector<int>その後にコピーコンストラクター呼び出しが続きます。2番目は直接初期化であり、明示的な変換を実行します。explicitマークされたコンストラクターが削除され、あいまいさが解消されるため、暗黙的な変換の候補のセットは少なくなります。

Clang 3.0と3.1の違いは、ライブラリコンプライアンスの修正であり、explicitコンパイラの動作の変更ではなく、追加のコンストラクタをとしてマークした可能性があります。

于 2012-10-24T21:37:19.167 に答える