在全局名称空间中声明一个朋友函数,该函数返回模板类

问题描述

我有一个在命名空间中声明的函数,当将该函数定义为朋友时,会引发编译器错误

#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();
};

这无法编译并显示错误

'class std :: vectorstd :: __ cxx11 :: basic_string '中的'Example'没有命名类型 朋友std :: vectorstd :: string :: Example :: GetNames(); ^ ~~~~~~ main.cpp:25:2:错误:预期为';'在类定义之后

但是,如果我从::删除了全局命名空间标识符::Example::GetNames(),它将很高兴地进行编译。

由于命名空间嵌套而需要从全局命名空间开始时,该如何处理?

解决方法

编译器不会按您的预期评估您的朋友声明。而是,编译器读取以下内容:

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

它认为您想声明GetNames类内部命名空间Example中的函数vector
这就是为什么当您删除::时,编译器可以查找命名空间Example本身并在全局命名空间中找到它。

您想要告诉编译器有一个名为Example的全局命名空间,是在函数声明的两边加上括号:

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

现在,您可以根据需要对其进行评估了。