У меня есть два класса, класс B
имеет член A1
, а класс A1
имеет ссылочный член B
, это легко написать так:
class B;
class A1 {
public:
A1(const B& b) : b_(b) {}
private:
const B& b_; // a reference to B
};
class B {
public:
B(A1 a1) : a1_(a1) {}
private:
A1 a1_; // a Type A1 member
};
А затем мне нужно изменить класс B
на класс шаблона, поэтому код должен выглядеть следующим образом:
template<typename T1>
class B;
class A1 {
public:
A1(const B<A1> &b) : b_(b) {};
private:
const B<A1> &b_; // a reference to B<A1>
};
template<typename T1>
class B {
public:
B(T1 t1) : t1_(t1){}
private:
T1 t1_; //a T1 type member
};
И вдруг нам нужен второй член в B
, поэтому я изменил B
к этому:
template<typename T1, typename T2>
class B {
public:
B(T1 t1, T2 t2) : t1_(t1), t2_(t2){}
private:
T1 t1_;
T2 t2_;
};
Это вызвало проблему:
теперь, если я кодировщик A
, приведенный ниже код недопустим:
template<typename T1, typename T2>
class B;
class A1 {
public:
A1(const B<A1> &b) : b_(b) {}; //wrong, need a second template argument
private:
const B<A1> &b_; // wrong, either
};
Это означает, что кодер должен заполнить второй аргумент шаблона, который он может не знать (или, по крайней мере, может не заботиться).Поэтому я изменяю код на это:
template <typename T1, typename T2>
class B;
template <typename TB>
class A1 {
public:
explicit A1(const TB& b) : b_(b) {}
private:
const TB& b_;
};
template <typename TB>
class A2 {
public:
explicit A2(const TB& b) : b_(b) {}
private:
const TB& b_;
};
template <typename T1, typename T2>
class B {
public:
B(T1 a1, T2 a2) : a1_(a1), a2_(a2) {}
private:
T1 a1_;
T2 a2_;
};
Это выглядит хорошо, за исключением того, что я не знаю, как сделать экземпляр B
(например: B<A1<B<A1<...>,A2>, A2>
, это рекурсивно.)
Идеальный дизайн, который я с нетерпением жду, заключается в том, что программистам для A1
и A2
просто не нужно знать друг друга, а программисту для B
просто нужно добавить A1
и A2
больше илименее похоже на это B<A1, A2>
(или добавьте еще кое-что), и даже если он добавит параметр T3
, такой как B<A1, A2, A3>, the code of
A1 and
A2`, изменять его не нужно.
Итак
1: Если я настаиваю на этом синтаксисе, означает ли это, что я должен отказаться от использования шаблона для B
, вместо этого использовать указатели?
2: Если я настаиваю на использовании шаблона, означает ли это, что класс T1
и класс T2
должны знать друг друга?
3: существует ли третий способ использования шаблона приT1
и T2
независимы?То есть независимо от того, сколько параметров я добавляю в класс B
, класс A1
менять не нужно?Шаблон template / CRTP / SFINAE, все это кажется бесполезным.Поскольку класс B
является только ссылкой в классе A
, класс B
больше похож на интерфейс, чем на определенный класс, это напоминает мне о предложении C ++ «концепция», может ли «концепция» помочь в этомcase?
4: Это проблема xy?Это означает, что я не должен разрабатывать свой шаблон кода таким образом?