Search code examples
c++classfriend

declaring a friend function in the global namespace that returns a template class


i have a function declared in a namespace, that when it is defined as a friend, throws a compiler error.

#include <string>
#include <vector>

namespace Example
{
    std::vector<std::string> GetNames();
}

class MyClass
{
    public:
        MyClass() : 
                name("data")
        {}

    private:
        std::string name;

    friend std::vector<std::string> ::Example::GetNames();
};

this fails to compile with the error

'Example' in 'class std::vectorstd::__cxx11::basic_string<char >' does not name a type friend std::vectorstd::string ::Example::GetNames(); ^~~~~~~ main.cpp:25:2: error: expected ';' after class definition

yet if i remove the global namespace identifier, :: from ::Example::GetNames(), it will compile happily.

how do i deal with this issue when i need to start at the global namespace due to nested namespaces?


Solution

  • The compiler doesn't evaluate your friend declaration as you intended it to. Instead, the compiler reads the following:

        friend std::vector<std::string>::Example::GetNames();
    

    It thinks that you want to declare the function GetNames that is within a namespace Example inside the vector class.
    That's why when you remove the :: the compiler can lookup the namespace Example itself and finds it in the global namespace.

    What you want to do instead to tell the compiler that there is a global namespace called Example is to put parentheses around the function declaration:

        friend std::vector<std::string> (::Example::GetNames)();
    

    Now, this gets evaluated as you want to.