1 に答える
何が問題なのかを理解するには、次の実装例を確認するistream_iterator
必要があります (問題は、ここに暗黙的に示されている標準の要件から発生します)。
template < class T, class CharT, class Traits, class Distance >
class istream_iterator
{
/* ... */
typedef std::basic_istream<CharT, Traits> istream_type;
istream_type* stored_istream_ptr;
T value;
public:
/* ... */
istream_iterator& operator++()
{
*stored_istream_ptr >> value; // (A)
return *this;
}
T const& operator*() const
{
return value;
}
/* ... */
};
行 (A) では、依存型のオブジェクトに演算子が適用されます。
value
タイプですT
stored_istream_ptr
type ですistream_type
。 typedef を参照してください
[temp.dep.type]/8 によると、両方のタイプが依存しています。
式A >> B
と他の関数呼び出しの場合、最初に関数の名前が検索されます (ここでは: operator>>
) -> name lookup、次に、見つかった関数 (オーバーロード) のセットから、最も実行可能なものが選択され、呼び出されます - >オーバーロード解決。
演算子の場合、メンバー関数と非メンバー関数 (ユーザーの演算子など) の両方が検索されます。
この場合、関連する型は依存しているため、名前検索の特別なルールが適用されます [temp.dep.res]/1:
従属名の解決では、次のソースからの名前が考慮されます。
- テンプレートの定義時に表示される宣言。
- インスタンス化コンテキスト (14.6.4.1) と定義コンテキストの両方からの関数引数の型に関連付けられた名前空間からの宣言。
演算子は、どちらにも関連付けられていないグローバル名前空間で定義されていstd::basic_istream
ますstd::pair
。したがって、名前解決は演算子を見つけられず、行 (A) の式のオーバーロード解決は失敗します。
これは、clang 3.2 のエラー メッセージを説明します。
stream_iterator.h:120:17: エラー: バイナリ式 ('istream_type' (別名 'basic_istream < char, std::char_traits >') および 'std::pair') に対するオペランドが無効です
*_M_stream >> _M_value; ~~~~~~~~~~ ^ ~~~~~~~~
そして、回避策が機能する理由を説明します。
一方、g++ は、名前解決によって見つかった 1 つのオーバーロードとそれが拒否された理由のみを表示しているようです (一方、clang++ は、名前解決によって見つかったすべてのオーバーロードと、それが拒否されたすべての理由を示します)。g++ が示すものは、「最適」である可能性があります。
template< class CharT, class Traits, class T >
basic_istream<CharT,Traits>& operator>>(basic_istream<CharT,Traits>&&, T&);
これは、私の知る限り、式が右辺値で動作するoperator>>
場合に他のラッパーを呼び出すだけです(のように)。istream_obj >> value
get_istream() >> value
これはあなたの問題とは関係ありません(そして紛らわしいです)。
2 つの回避策:
- ラッパー タイプを使用してラップし、そのラッパー タイプに関連付けられた名前空間で
std::pair
を定義できるようにします。operator>>
- 名前空間 std に演算子を挿入します (非推奨??)