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;