Как вызвать конструктор с одним аргументом в этой программе, включающий шаблон класса?

Это код, который я написал, чтобы начать работу с шаблонами классов.

#include<iostream>
using namespace std;
template<class T>
class Complex
{
T *real,*imag;
public:
    Complex(T a)
    {
    real=new T;
    imag=new T;
        *real=a;
        *imag=0;
    }
    Complex(T a,T b)
    {
    real=new T;
    imag=new T;
        *real=a;
        *imag=b;
    }
    Complex()
    {
    real=new T;
    imag=new T;
        *real=0;
        *imag=0;
    }   
template<class R>       
friend ostream& operator<<(ostream &out,Complex<R> &C);
template<class R>
friend istream& operator>>(istream &in,Complex<R> &C);
template<class R>
friend Complex<R> operator +(Complex<R> a,Complex<R> b);    
};
template<class R>
ostream& operator<<(ostream &out,Complex<R> &C)
    {
    out<<"The number is "<<*C.real<<"+"<<*C.imag<<"i"<<endl;
    return out; 
    }
template<class R>       
istream& operator>>(istream &in,Complex<R> &C)
    {
    cout<<"Enter the number ";
    in>>*C.real>>*C.imag;
    return in;  
    }
template<class R>       
Complex<R> operator +(Complex<R> a,Complex<R> b)
{
Complex<R> temp;
*temp.real=*a.real+*b.real;
*temp.imag=*a.imag+*b.imag;
return temp;    
}       
int main()
{
Complex<float> C1,C2(4.2,6.8),C3,C4;
C1=5;
C3=3+C1;
C4=C2+C3;
cout<<C1;
cout<<C2;
cout<<C3;
cout<<C4;
}

В этом коде все отлично работает, за исключением того, что когда я пытаюсь использовать целочисленное значение, например "3 + C2", он показывает ошибку. Если один и тот же код рассматривается без использования шаблонов для '3+C2', вызывается оператор дружественной функции +(Complex a,Complex b) и 3, копируемый в объект a, который вызывает конструктор с одним аргументом, а 3 будет назначена действительной части Комплексный класс. Как сделать то же самое, когда используются шаблоны классов? Как вызвать конструктор с одним аргументом, когда число передается функции operator+() вместо объекта Complex, когда используются шаблоны классов?

1 ответ

С чем-то вроде

template<class R>
Complex<R> operator +(Complex<R>, Complex<R>);

Тип R выводится независимо от каждого аргумента функции; оба вывода должны быть успешными, и выводимый тип должен совпадать, чтобы это можно было использовать. Поскольку 3 не является Complex, вычет не выполняется и перегрузка не учитывается.

Есть два способа решить это. Одним из них является использование не шаблонного друга:

template<class T>
class Complex {
   // ...
   friend Complex operator+(Complex a, Complex b) {
      // ...
   }
};

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

Другой подход заключается в предоставлении дополнительных перегрузок, которые определяются только из одного аргумента:

template<class T> struct identity { using type = T; };
template<class T> using nondeduced_t = typename identity<T>::type;

template<class R>
Complex<R> operator +(nondeduced_t<Complex<R>>, Complex<R>) { /* ... */ }

template<class R>
Complex<R> operator +(Complex<R>, nondeduced_t<Complex<R>>) { /* ... */ }

Это подход, принятый std::basic_string_view,


Кстати, реализация у вас сильно нарушена. Утечка памяти, как будто нет завтрашнего дня - и нет причин динамически распределять Tв первую очередь.

Другие вопросы по тегам