I have a main class MainClass
whose private member variables should be visible to a friend class FriendClass
.
Both are templated by an int
called dim
, and they both have their respective header and source files (and are thus in different translation units).
Since MainClass
doesn't really depend on FriendClass
(and to avoid circular dependency) I forward declare FriendClass
as a template class when doing the friend declaration in MainClass
.
Additionally, at the end of the source files I explicitly instantiate both classes for dim = 2
and dim = 3
.
However, when I compile I get an error that the private member variable of MainClass
is private within this context when I try to use it in a method of FriendClass
.
I suspect this has something to do with the fact that a particular instantiation of FriendClass
does not recognize that the corresponding instantiation of MainClass
has declared it a friend, but I'm not sure how to fix the problem.
Code:
// MainClass.hpp
#ifndef MAIN_CLASS_HPP
#define MAIN_CLASS_HPP
template <int dim>
class MainClass
{
public:
MainClass(){};
private:
template <int friend_dim>
class FriendClass;
friend class FriendClass<dim>;
double private_member = 3.0;
};
#endif
// MainClass.cpp
#include "MainClass.hpp"
template class MainClass<2>;
template class MainClass<3>;
// FriendClass.hpp
#ifndef FRIEND_CLASS_CPP
#define FRIEND_CLASS_CPP
#include "MainClass.hpp"
template <int dim>
class FriendClass
{
public:
FriendClass(){};
void print_main_class(MainClass<dim> &main_class);
};
#endif
// FriendClass.cpp
#include "FriendClass.hpp"
#include <iostream>
template <int dim>
void FriendClass<dim>::print_main_class(MainClass<dim> &main_class)
{
std::cout << main_class.private_member << std::endl;
}
template class FriendClass<2>;
template class FriendClass<3>;
// main.cpp
#include "MainClass.hpp"
#include "FriendClass.hpp"
int main()
{
const int dim = 2;
MainClass<dim> main_class;
FriendClass<dim> friend_class;
friend_class.print_main_class(main_class);
return 0;
}
Code available to compile live at onlinegdb.com
You have declared two different class templates both named FriendClass
. Probably unintentionally.
One is the global FriendClass
and the other is MainClass::FriendClass
.
You can fix this by forward declaring your class template in the namespace it exists in.
// MainClass.hpp
#ifndef MAIN_CLASS_HPP
#define MAIN_CLASS_HPP
template <int>
class FriendClass;
template <int dim>
class MainClass
{
public:
MainClass(){};
private:
friend FriendClass<dim>;
// Now the global FriendClass is a friend.
double private_member = 3.0;
};
#endif