0

Consider the below code.

struct foo {
  friend foo create(foo) { return {}; }
};

int main() {

  auto a = create(foo{});

  return 0;
}

This code compiles perfectly on all compilers.

But the next below code compiles only in MSVC.

struct foo {};

struct bar {
  friend bar create(foo) { return {}; }
};

int main() {

  auto a = create(foo{});

  return 0;
}

Other compilers, such as gcc, clang fail to compile with the following error.

error: 'create' was not declared in this scope
   9 |   auto a = create(foo{});

Is this non-standard?

I'm working on some template thing, so I must declare the friend function inside of the bar.
Is there any way to achieve it?

김선달
  • 1,485
  • 9
  • 23

2 Answers2

1

See https://en.cppreference.com/w/cpp/language/friend

A name first declared in a friend declaration within a 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 - see namespaces for details.

Visual studio is not complying with the standard here, your first version works as the use of foo triggers ADL.

One option is to also declare the function outside the class:

struct foo {};

struct bar {
  friend bar create(foo) { return {}; }
};

bar create(foo);

int main() {

  auto a = create(foo{});

  return 0;
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
0

Solved with declaring in foo with return type auto.
It only works in C++ >= 14, but compiled in gcc >= 6.0, clang >= 8.0.

struct foo {
  friend auto create(foo);
};

struct bar {
  friend auto create(foo) { return bar{}; }
};

int main() {

  auto a = create(foo{});

  return 0;
}
김선달
  • 1,485
  • 9
  • 23
  • No need of `auto` [Demo](https://godbolt.org/z/nzKEvWxxe). you added a `friend` declaration in `foo` which is found by ADL (and defined in `bar`). – Jarod42 Apr 26 '21 at 07:38