циклические зависимости в специализациях функций-членов…… «создание экземпляра до специализации»

#c #function #templates #member #template-specialization

Вопрос:

приведенный ниже код не компилируется

 #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);
}

 

в качестве специализированного метода «записи» A и B создают экземпляр шаблона «добавления» A или B. При компиляции жалобы компилятора

 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;};
 

На данный момент я не вижу, как можно упорядочить функции, чтобы избежать этой проблемы, за исключением того, что я отказываюсь от специализации.

Любые предложения высоко ценятся.

Ответ №1:

Вы можете объявлять специализации методов шаблона после каждого объявления класса:

 #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);
}
 

В коде есть комментарий о том, что метод B<int>::add(A<int> x) вызывается, A<int>::write(B<int> x) но не был объявлен или определен ранее.

Комментарии:

1. это сделало свое дело. потрясающе.