【发布时间】:2013-02-28 16:14:07
【问题描述】:
我遇到了在我看来 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 都通过它们的 friend 声明注入到命名空间 test 中,因此它们都不应该真正存在于全局命名空间中。
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 指令)“@在using 指令处,987654336@ 尚未声明”(test::bar 也是如此)。
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 出了什么问题?
欢迎回答任何子问题。
【问题讨论】:
标签: c++ templates c++11 namespaces friend