Home > Blockchain >  Making a class template declared in an outer anonymous namespace a friend
Making a class template declared in an outer anonymous namespace a friend

Time:10-20

Clang refuses to compile the following code (godbolt) while gcc sees no problem with it. Clang error message is shown below line marked (2):

namespace  // Overall anonymous namespace is required and cannot be removed.
{

template <typename T>
struct Friend;

namespace ns
{

class Secret
{
    template <typename T>
    friend struct Friend;     // (1)

    static void foo() {}
};

} // namespace ns

template <typename T>
struct Friend
{
    void bar()
    {
        ns::Secret::foo();   // (2)
        // Error at line (2):
        // 'foo' is a private member of '(anonymous namespace)::ns::Secret'
    }
};

} // anonymous namespace

The reason, I assume, is that line (1) is treated as a declaration of a new class template struct ns::Friend<T> rather than a reference to ::(anonymous namespace)::Friend<T>.

The questions are:

  1. Who's right -- clang or gcc?
  2. If clang is right, then is there a way to make it understand that line (1) doesn't introduce new class template, but refers to existing one?

CodePudding user response:

Yes, you are right that simply friend struct Friend is a declaration of a templated class ::(anonymous namespace)::ns::Friend. Both compilers are right, as when you attempt to use Friend<T>::bar() gcc will complain about access as well (clang just checks a lot earlier than gcc)

To specify the class template in the global namespace, you must write that out:

    template <typename T>
    friend struct ::Friend;     // (1)

This works for GCC, but clang seems broken and doesn't find Friend in the global namespace.

These two workarounds seem to work:

// Make the entire unnamed namespace an inline namespace
inline namespace
{
// ...
}


// Add an explicit using directive to help clang find Friend in `::`
namespace {

template<typename T>
struct Friend;

}
using ::Friend;
namespace {
namespace ns {
// ...
}
}
  • Related