问题
The following simple code compiles fine
class A {
int x[3];
public:
A() { x[0]=1; x[1]=2; x[2]=3; }
friend int const&at(A const&a, unsigned i) noexcept
{
return a.x[i];
}
friend int foo(A const&a, unsigned i) noexcept
{
int tmp = at(a,i);
return tmp*tmp;
}
};
but if the friends are made templates
class A {
int x[3];
public:
A() { x[0]=1; x[1]=2; x[2]=3; }
template<unsigned I>
friend int const&at(A const&a) noexcept
{
static_assert(I<3,"array boundary exceeded");
return a.x[I];
}
template<unsigned I>
friend int foo(A const&a) noexcept
{
int tmp = at<I>(a); // <- error: use of undeclared identifier 'at'
return tmp*tmp;
}
};
the look-up rules change and clang complains with said error, but gcc and icpc don't. Who is right (C++11)? and how to get the code fixed for clang?
回答1:
The fix is to separate declaration and definition:
class A {
int x[3];
public:
A() { x[0]=1; x[1]=2; x[2]=3; }
template<unsigned I>
friend int const&at(A const&a) noexcept;
template<unsigned I>
friend int foo(A const&a) noexcept;
};
template<unsigned I>
int const&at(A const&a) noexcept
{
static_assert(I<3,"array boundary exceeded");
return a.x[I];
}
template<unsigned I>
int foo(A const&a) noexcept
{
int tmp = at<I>(a);
return tmp*tmp;
}
来源:https://stackoverflow.com/questions/15745776/templated-friend-function-lookup