由于相互标头包含,无法成功地与模板化类中的模板化方法交朋友

Cannot successfully friend a templated method in a templated class because of mutual header inclusion

本文关键字:交朋友 方法 于相互 包含 成功      更新时间:2023-10-16

我有一个包装矩阵管理逻辑的类。同时,我有一套专门用于处理一些重要的时间花费矩阵操作操作(如 LU 分解等)的方法。

该类使用该文件中定义的函数。该文件需要有权访问该类的元素。我需要使这些专业方法成为上述班级的朋友。这导致我在彼此的标题中包含一个标题。

我的问题

我之前描述的情况在这里编码如下。第一个代码是指mat.hpp

#ifndef MAT_HPP
#define MAT_HPP
#include "operations.hpp"
namespace nsA {
template <typename T>
// Templated class because matrices can be real or complex
class mat {
   // Members...
   friend template <typename U> 
   void exec_lu(const mat<U>& in, const mat<U>& out);
   // Members...
} /* class end */
}
#endif
#endif

第二个文件是operations.hpp

#ifndef OPERATIONS_HPP
#define OPERATIONS_HPP
#include "mat.hpp"
namespace nsA {
namespace nsB {
template <typename T>
void exec_lu(const mat<T>& in, const mat<T>& out);
}
}
#endif

问题是编译器开始抱怨。

注意

请考虑一下,如果我在mat.hpp中注释朋友声明但保留包含,编译器告诉我在"operations.hpp"中未定义mat类型!

如果还注释包含在mat.hpp中并保持朋友声明注释,则编译器就可以了!

如何解决这个问题?

谢谢

您只需添加几个前向声明即可做到这一点...但是你甚至可以用更多的代码做得更好:

template <typename T> class mat;
template <typename T> void exec_lu( const mat<T>&, const mat<T>& );
template <typename T>
class mat {
   friend void exec_lu<T>( const mat<T>&, const mat<T>& );
};
template <typename T>
void exec_lu( const mat<T>& a, const mat<T>& b ) { ... }

这种方法和你的方法之间的主要区别(除了修复语法限制)是,在这种方法中,exec_lu的单个实例被授予对mat<T>的访问权限,特别是需要访问它的实例化。在您的代码中(修复后),exec_lu的所有特化都可以访问mat的任何特化(即 exec_lu<int>可以访问mat<int>私人成员,但也可以访问mat<double>......你可能不想这样。

有关声明模板之友的不同选项的详细说明,请阅读相关问题的此答案。

要使其正常工作,您需要转发声明该类。它看起来像这样:

文件mat.hpp:

#ifndef MAT_HPP
#define MAT_HPP
namespace nsA {
template <typename T>
class mat;
namespace nsB {
  template <typename T> 
  void exec_lu(const mat<T>& in, const mat<T>& out);
}
template <typename T>
class mat {
   friend void exec_lu(const mat<T>& in, const mat<T>& out);
};
}
#endif

和文件操作.hpp:

#ifndef OPERATIONS_HPP
#define OPERATIONS_HPP
#include "mat.hpp"
namespace nsA { namespace nsB {
template <typename T>
void exec_lu(const mat<T>& in, const mat<T>& out);
}}
#endif

你最初的宣言比我更能表达出友谊。我的只为与类的类型名匹配的函数授予友谊。