我遇到了在我看来 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;
}
gcc(4.7.0,使用 std=c++11)抱怨“foo
未在此范围内声明”(并建议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有什么问题?
欢迎回答任何子问题。