使用 friend class 减少编译时间和依赖性
Reduce compilation times and dependencies using friend class
在我的一个项目中,我有一个树数据结构,它可能包含泛型类型的值 T
。
为了减少编译时间和依赖性,我尝试将实现细节从树节点 class Node
移动到 class NodeImpl
。 Node
的内部是私有的,只能在定义的入口点访问,例如通过 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] 表明此解决方案确实有效。
在我的一个项目中,我有一个树数据结构,它可能包含泛型类型的值 T
。
为了减少编译时间和依赖性,我尝试将实现细节从树节点 class Node
移动到 class NodeImpl
。 Node
的内部是私有的,只能在定义的入口点访问,例如通过 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] 表明此解决方案确实有效。