1

The following example compiles BUT gcc warns me that the friend declaration is in fact not a templated function. I don't understand what exactly I'm supposed to change. Clang and MSVC accept this code without any issues.

In this this question it is implied that you're supposed to put template <typename T> in front of the in-class friend declaration, but then gcc complains about shadowing T.

Demo

#include <memory>
#include <cstdio>

/* header.hpp */

template <typename T>
class entity;

template <typename T>
auto create_entity() -> std::shared_ptr<entity<T>>;

template <typename T>
class entity
{
    // template <typename T>
    friend auto create_entity() -> std::shared_ptr<entity<T>>;
};

/* impl.cpp */

template <typename T>
auto create_entity() -> std::shared_ptr<entity<T>> {
    return std::make_shared<entity<T>>();
}

int main()
{
    create_entity<int>();
}

Warning:

<source>:16:41: warning: friend declaration 'std::shared_ptr<entity<T> > create_entity()' declares a non-template function [-Wnon-template-friend]
   16 |     friend auto create_entity() -> std::shared_ptr<entity<T>>;
      |                                         ^~~~~~~~~~~~~~~~~~~~~
<source>:16:41: note: (if this is not what you intended, make sure the function template has already been declared and add '<>' after the function name here)

How do I resolve this issue (for gcc)?

glades
  • 3,778
  • 1
  • 12
  • 34

1 Answers1

2

Identifiers used for template parameters may not be re-used inside the template for any other purpose. In other words, they may not be shadowed.

If you want any create_entity<U> to be a friend of entity<T>, change the inner T to U:

template <typename T>
auto create_entity() -> std::shared_ptr<entity<T>>;

template <typename T>
struct entity
{
    template <typename U>
    friend auto create_entity() -> std::shared_ptr<entity<U>>;
};

If you want only create_entity<T> to be a friend of entity<T>:

template <typename T>
auto create_entity() -> std::shared_ptr<entity<T>>;

template <typename T>
struct entity
{
    friend auto create_entity<T>() -> std::shared_ptr<entity<T>>;
};
rustyx
  • 80,671
  • 25
  • 200
  • 267