Home > Software design >  circular dependencies in member function specializations ....... "instantiation before speciali
circular dependencies in member function specializations ....... "instantiation before speciali

Time:09-21

the code below doesn't compile

#include <iostream>
using namespace std;
template<class T> class A;
template<class T> class B;
//@@@@@@@@@@@@@y
template<class T>
class B{
  int x=1;
public:
  void write(A<T> x);
  void add(A<T> x);
};
template<class T>
class A{
  int x=1;
public:
  void write(B<T> x);
  void add(B<T> x);
};

template<class T> void A<T>::write(B<T> x){cout<<"write generic A"<<endl;x.add(*this);};
template<class T> void A<T>::add(B<T> x){cout<<"add generic A"<<endl;};

template<> void A<int>::write(B<int> x){cout<<"write special A"<<endl;x.add(*this);};
template<> void A<int>::add(B<int> x){cout<<"add special A int"<<endl;};


template<class T> void B<T>::write(A<T> x){cout<<"write generic B"<<endl;x.add(*this);};
template<class T> void B<T>::add(A<T> x){cout<<"add generic B"<<endl;};

template<> void B<int>::write(A<int> x){cout<<"write special B"<<endl;x.add(*this);};
template<> void B<int>::add(A<int> x){cout<<"add special B"<<endl;};





int main(){
  B<int> b;
  A<int> a;
  b.write(a);
}

as the specialized "write" method of A and B instantiate a template of "add" of A or B. When compiling the compiler complaints

error: specialization of ‘void B<T>::add(A<T>) [with T = int]’ after instantiation
   32 | template<> void B<int>::add(A<int> x){cout<<"add special B"<<endl;};

I cannot see at the moment how the functions can be ordered to avoid this problem, except I drop the specialization.

Any suggestions highly appreciated.

CodePudding user response:

You can declare specializations of template methods after each class declaration:

#include <iostream>
using namespace std;
template<class T> class A;
template<class T> class B;
//@@@@@@@@@@@@@y
template<class T>
class B{
  int x=1;
public:
  void write(A<T> x);
  void add(A<T> x);
};
// declare specializations:
template<> void B<int>::write(A<int> x);
template<> void B<int>::add(A<int> x);

template<class T>
class A{
  int x=1;
public:
  void write(B<T> x);
  void add(B<T> x);
};
// declare specializations:
template<> void A<int>::write(B<int> x);
template<> void A<int>::add(B<int> x);

template<class T> void A<T>::write(B<T> x){cout<<"write generic A"<<endl;x.add(*this);};
template<class T> void A<T>::add(B<T> x){cout<<"add generic A"<<endl;};

template<> void A<int>::write(B<int> x){cout<<"write special A"<<endl;x.add(*this);}; // method "B<int>::add(A<int> x)" is called but was not declared or defined before
template<> void A<int>::add(B<int> x){cout<<"add special A int"<<endl;};


template<class T> void B<T>::write(A<T> x){cout<<"write generic B"<<endl;x.add(*this);};
template<class T> void B<T>::add(A<T> x){cout<<"add generic B"<<endl;};

template<> void B<int>::write(A<int> x){cout<<"write special B"<<endl;x.add(*this);};
template<> void B<int>::add(A<int> x){cout<<"add special B"<<endl;};


int main(){
  B<int> b;
  A<int> a;
  b.write(a);
}

There is a comment in the code about method B<int>::add(A<int> x) is called in A<int>::write(B<int> x) but was not declared or defined before.

  • Related