私には、C++ コンパイラの矛盾のように見えるものに遭遇しました。次のコード例では
#include <vector>
namespace test {
class A : std::vector<int>
{
template<typename F>
friend void bar(A const&a, F f) { for(auto i:a) f(i); }
template<int K, typename F>
friend void foo(A const&a, F f) { for(auto i:a) if(i&K) f(i); }
};
}
int sum(test::A const&a)
{
int s=0;
foo<2>(a,[&s](int i) { s+=i; } ); // <-- error here
bar (a,[&s](int i) { s+=i; } ); // <-- but not here
return s;
}
foo
gcc (4.7.0、std=c++11 を使用) は、「このスコープで宣言されていませんでした」(および代替案として提案) について不平を言いますが、次の行でtest::foo
の使用法を喜んでコンパイルします。bar
現在、foo
との両方が宣言bar
によって名前空間に挿入されているため、どちらも実際にはグローバル名前空間に存在する必要はありません。test
friend
Q1私は間違っていますか、それともこれは c++11 の新しいひねりですか、それとも gcc の動作がおかしいのでしょうか?
もちろん、using ディレクティブをグローバル名前空間に単純に挿入すれば、この問題は回避されます。しかし、A
テンプレートを作ると、
#include <vector>
namespace test {
template<typename T>
class A : std::vector<T>
{
template<typename F>
friend void bar(A const&a, F f) { for(auto i:a) f(i); }
template<int K, typename F>
friend void foo(A const&a, F f) { for(auto i:a) if(i&K) f(i); }
};
}
using test::foo; // does not avoid compilation error
using test::bar; // does not avoid compilation error
int sum(test::A<int> const&a)
{
int s=0;
foo<2>(a,[&s](int i) { s+=i; } );
bar (a,[&s](int i) { s+=i; } );
return s;
}
gcc は再び文句を言います。(using
ディレクティブなしで)「foo
このスコープで宣言されていません」(しかし、再び喜んでコンパイルしますbar
が、示唆していませんtest::foo
)または(using
ディレクティブを使用して)「test::foo
宣言されていません」(および同じtest::bar
)のポイントでusing
指令。
Q2これは、コンパイラ エラーのように見えます。using
ディレクティブの有無に関係なく、 を呼び出すことはできませんtest::foo
。それとも、C++ について見逃したことがあるのでしょうか。
最後に、次のようにフレンド定義をクラスの外に移動しようとしました
namespace test {
template<typename T>
class A : std::vector<int>
{
template<int K, typename F>
friend void foo(A const&a, F f);
template<typename F>
friend void bar(A const&a, F f) { for(auto i:a) f(i); }
};
template<int K, typename T, typename F>
void foo(A<T> const&a, F f) { for(auto i:a) if(i&K) f(i); }
}
using test::foo;
gcc が再び不平を言うと、今回はそれvoid test::foo(const test::A<T>&, F)
が使用されているが定義されていないと主張しています... Q3何が問題なのですか?
サブ質問への回答は歓迎します。