Sometimes we have two classes that need to call each other’s somewhat function, for example
template <typename A>
struct B
{
A* p_a_ = nullptr;
};
template <typename B>
struct A
{
B* p_b_ = nullptr;
};
but as you can see A depends on B’s type to initialize and vise versa. If we declare the types as above we’ll not get a chance to create any instance.
There are at least two ways to resolve the issue.
I.Template template
A quick introduction about template template can be found here.
Declare either of {A, B} with template of template which accepts the other’s template argument.
template <template<typename> typename A_t>
struct B
{
using A = A_t<B>;
A* p_a_ = nullptr;
};
template <typename B>
struct A
{
B* p_b_ = nullptr;
};
//and declare like this
using B_t = B<A>;
B_t b_instance;
A<B_t> A_instance;
II.Type traits
The other resolution is create a type trait struct which acts like a bridge that links the type of each other.
template <typename foobar_tratis>
struct foobar_notifier
{
using inst_t = typename foobar_tratis::foobar_inst_t;
inst_t* inst_ = nullptr;
void foobar()
{
std::cout << "foobar_notifier" << std::endl;
}
};
template <typename foobar_tratis>
struct foobar_inst
{
using notifier_t = typename foobar_tratis::foobar_notifier_t;
notifier_t* notifier_ = nullptr;
void foobar()
{
std::cout << "foobar_inst" << std::endl;
}
};
struct foobar_tratis
{
using foobar_notifier_t = foobar_notifier<md_inst_traits>;
using foobar_inst_t = foobar_inst<md_inst_traits>;
};
/// and declare like this
foobar_inst<foobar_tratis> inst2;
foobar_notifier<foobar_tratis> notifier2;