class with friend rather than forward declaration,: which compiler is correct [duplicate]
Asked Answered
A

1

6

I have this simple C++ program:

#include <iostream>

struct obj {
  friend int f(int);

  void m(int x) { std::cout << "f(" << x << ") = " << f(x) << std::endl; }
};

int main() {
  obj o;
  o.m(21);
}


int f(int x) {
  return 2*x;
}

If I compile with the GNU C++ compiler g++, I get the error prog.cpp:7:55: error: 'f' was not declared in this scope

However, if I compile it with cl (and /W4) it compiles and executes fine.

I am not sure which compiler is correct.

Alpaca answered 23/7, 2019 at 12:24 Comment(0)
V
3

From cppreference on friend declaration:

A name first declared in a friend declaration within class or class template X becomes a member of the innermost enclosing namespace of X, but is not visible for lookup (except argument-dependent lookup that considers X) unless a matching declaration at the namespace scope is provided

A matching declaration at global scope is provided, but only after the definition of obj::m(). I think it's correct to refuse the call to f at this point. You can see the effect e.g. this compiles with both gcc and clang,

int f(int);

class obj { /* as before... */ };

and so does this:

struct obj {
  friend int f(int);

  void m(int x); 
};

int f(int);

void obj::m(int x) { std::cout << "f(" << x << ") = " << f(x) << std::endl; }
Velar answered 23/7, 2019 at 12:38 Comment(1)
Or friend int f(obj const&, int); so ADL would have worked by adding that first parameter (even if it is a dummy parameter).Diencephalon

© 2022 - 2024 — McMap. All rights reserved.