これは奇妙で、C++ 標準によるものなのか、私のコンパイラ (Ubuntu の最新の長期サポート バージョンである Ubuntu 12.04 上の G++ バージョン 4.6.3) によるものなのか、それとも私自身によるものなのかはわかりません。わかりません;-)
問題のコードは次のように単純です。
#include <algorithm> // for std::swap
void f(void)
{
class MyClass { };
MyClass aa, bb;
std::swap(aa, bb); // doesn't compile
}
G++ でコンパイルしようとすると、コンパイラは次のエラー メッセージを生成します。
test.cpp: In function ‘void f()’:
test.cpp:6:21: error: no matching function for call to ‘swap(f()::MyClass&, f()::MyClass&)’
test.cpp:6:21: note: candidates are:
/usr/include/c++/4.6/bits/move.h:122:5: note: template<class _Tp> void std::swap(_Tp&, _Tp&)
/usr/include/c++/4.6/bits/move.h:136:5: note: template<class _Tp, long unsigned int _Nm> void std::swap(_Tp (&)[_Nm], _Tp (&)[_Nm])
驚くべき結果は、関数からクラス定義を移動するだけで、そのコードが正常にコンパイルされるということです。
#include <algorithm> // for std::swap
class MyClass { };
void f(void)
{
MyClass aa, bb;
std::swap(aa, bb); // compiles fine!
}
std::swap() は、関数に対してプライベートなクラスでは機能しないはずですか? それとも、これは G++ のバグですか、おそらく私が使用している G++ の特定のバージョンですか?
さらに不可解なのは、MyListClass も非公開であるにもかかわらず、以下が再び機能することです (ただし、swap() の特定の実装が存在する可能性がある「公式」クラスを拡張します)。
#include <algorithm> // for std::swap
#include <list> // for std::list
void g(void)
{
class MyListClass : public std::list<int> { };
MyListClass aa, bb;
std::swap(aa, bb); // compiles fine!
}
しかし、オブジェクトからポインターに変更するだけで、コンパイルは再び失敗します。
#include <algorithm> // for std::swap
#include <list> // for std::list
void g(void)
{
class MyListClass : public std::list<int> { };
MyListClass aa, bb;
MyListClass* aap = &aa;
MyListClass* bbp = &bb;
std::swap(aap, bbp); // doesn't compile!
}
もちろん、私の実際のアプリケーションでは、クラスはもっと複雑です。問題を再現するために、コードを可能な限り単純化しました。