使用 friend class 减少编译时间和依赖性

Reduce compilation times and dependencies using friend class

在我的一个项目中,我有一个树数据结构,它可能包含泛型类型的值 T

为了减少编译时间和依赖性,我尝试将实现细节从树节点 class Node 移动到 class NodeImplNode 的内部是私有的,只能在定义的入口点访问,例如通过 getName 函数。

只有对使用 getName 感兴趣的人才应该在他们的源文件中包含 NodeImpl。这就是我认为减少编译时间和依赖项的方式。

但由于某些原因,以下三个玩具 classes 将无法编译。它说无法访问私人成员。我做错了什么?

文件main.cpp:

#include <iostream>
#include "Node.h"
#include "NodeImpl.h"

int main(int argc, char** args) {
    Node<int> n("Test", 2);
    std::cout << getName(n) << std::endl;
}

文件Node.h:

#pragma once
#include <string>

template<typename T>
class NodeImpl;

template<typename T>
class Node {
public:
    typedef T value_type;
    Node(const std::string& name, const T& value) : name(name), value(value) {}

private:
    std::string name;
    T value;
    friend class NodeImpl<T>;
};

文件NodeImpl.h:

#pragma once
#include "Node.h"

template<typename T>
std::string getName(Node<T>& n);

template<typename T>
class NodeImpl {
    NodeImpl(Node<T>& node) : mNode(node) {
    }
    Node<T>& mNode;

    std::string name() {
        return mNode.name;
    }

    friend std::string getName(Node<T>& n);
};

template<typename T>
std::string getName(Node<T>& n) {
    auto x = NodeImpl<T>(n);
    return x.name();
}

warning produced by GCC 给出了见解:

warning: friend declaration 'std::__cxx11::string getName(Node<T>&)' declares a non-template function [-Wnon-template-friend]
 friend std::string getName(Node<T>& n);
                                      ^
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 

换句话说,您的 class NodeImpl<int> 与全局函数 std::string getName(Node<int> &) 成为朋友,该函数与从函数模板 [=15] 实例化的函数 std::string getName<int>(Node<int> &) 无关=] 对于 T = int.

所以正确的解决方案是这样的:

template<typename T>
class NodeImpl {
    // ... as before ...

    friend std::string getName<T>(Node<T>& n);
};

[live example] 表明此解决方案确实有效。