5

This surprised me. This works:

struct foo {
  int x;
  friend int x(foo f) { return f.x; }
  friend int y(foo f);
};

int y(foo f) { return x(f); } // no problem

But this is an error:

struct foo {
  int x;
  friend int x(foo f) { return f.x; }
  friend int y(foo f) { return x(f); } // error: invalid use of foo::x data member
};

Why aren't both of these (dis)allowed?

Daniel Daranas
  • 22,454
  • 9
  • 63
  • 116
dmitchell
  • 51
  • 2
  • 1
    Does `return ::x(f);` work? That should explicitly reference the `x()` in the global namespace. (If `x()` is not in the global namespace then try `::the::namespace::x(f)`.) – cdhowie Jul 25 '13 at 19:42
  • @cdhowie: "The name of the friend **is not found** by unqualified lookup **or by qualified lookup** until a matching declaration is provided in that namespace scope". Argument-dependent lookup is the only way to find it, or add a declaration above the class (since below the class is too late for an inline declaration of `friend int y()` to find it) – Ben Voigt Jul 25 '13 at 20:13
  • 1
    What kind of naming convention leads to a member variable and a friend function to share a name? That is the issue you really need to solve. – David Rodríguez - dribeas Jul 25 '13 at 20:20

1 Answers1

3

The reason is that in the first case, the friendship injected the function declaration into the enclosing namespace, so the global-scoped call to x can see only one x.

In the second example, x has two meanings at that scope: The global friend function and the variable (which presumably shadows the global friend function).

Mark B
  • 95,107
  • 10
  • 109
  • 188