Как мне использовать двоичные арифметические операторы в сочетании с шаблонами?

#c

#c

Вопрос:

Я написал номер класса, который содержит только один атрибут: значение T . В настоящее время я изучаю шаблоны, поэтому T — это тип данных. Чего я хочу добиться, так это выполнения следующего вида вычислений.

 Number<int>(2)   Number<double>(1.2)
 

То, что у меня есть до сих пор, может выполнять операцию, но она завершается неудачей при наличии двух разных типов данных. До сих пор я писал это:

 //class template

template<class T>
class Number
{
public:

    T value;

    Number(T num1)
    {
        value = num1;
    }

    Number<T> operator   ( const Number<T> amp;other) const
    {
        return Number<decltype(value other.value)> (value other.value);
    }

};
 

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

Вопросы:

  • Почему программа работает только с одними и теми же типами данных?

За часть этого я могу ответить сам. Я использую строку:

 Number<T> operator   ( const Number<T> amp;other) const
 

Итак, если левая сторона имеет тип int . Каждый T становится an int . Я не знаю, как мне нужно это изменить, не получая ошибки.

  • Что мне нужно исправить, чтобы выполнять вычисления с разными типами данных?

Редактировать:

Ограничение заключается в том, что шаблон может содержать только один аргумент типа

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

1. Вам нужно объявить operator , который принимает разные типы данных с левой и правой стороны, вместо operator, который принимает число<T> с обеих сторон.

2. Вам нужно что-то вроде этого: template<class T, class U> Number<std::common_type_t<T, U>> operator (const Number<T>amp;, const Number<U>amp;) . Предпочитаю operator определяться как свободная функция (возможно friend , одна).

3. на самом деле можно использовать тип возврата auto плюс завершающий, чтобы вычесть тип, выполненный во время компиляции. например auto operator (const Number<T> amp;, const Number<S> amp;) -> Number<decltype(a.value b.value)>; , или, если значение является частным, a.value b.value может быть заменено на std::declval<T>() std::declval<S>() . Более аккуратный, std::common_type::type(c 11)/std::common_type_t(c 14) также может быть использован.

4. @SHP откуда берутся переменные a и b? Я забыл упомянуть, что ограничением является то, что я могу использовать только один аргумент типа для шаблона. В результате я больше не могу использовать: const Number<S> . Что бы вы посоветовали мне сделать? Спасибо за ответ!

5. @Nadine Функция друга шаблона не изменяет способ объявления вашего класса, у вас все еще есть число<T1> a; и число<T2> b; параметр two template используется только в функции a b.

Ответ №1:

Помимо объявления оператора-друга с двумя предлагаемыми параметрами шаблона, вы также можете разместить дополнительный шаблон для функции-члена operator , что позволяет выполнять приведение plus .

 template<typename T>
class Number
 {
   public:
     T value;

     Number(const Tamp;num1)
      {
         value = num1;
      }

 template <typename X> auto operator   ( const Number<X> amp;other) const
      {
         auto c = this->value   other.value;
         return Number<decltype(c)> ( c );
      }
};
#include <iostream>
int main()
{
    Number<int> n{2};
    Number<double> a{3.4};
    std::cout << (a n).value << std::endl;
}
 

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

 template<typename T>
class Number
{
  public:

    T value;

    Number(T num1)
     {
        value = num1;
    }

   Numberamp; operator  =( const Number<T> amp;other)
    {
       this->value  = other.value;
       return *this;
    }
};
template <typename T1,typename T2> auto operator (const Number<T1>amp;a, const Number<T2>amp;b)
{
    auto c = a.value   b.value;       
    return Number<decltype(c)>( c );
}
 

Ответ №2:

 #include <iostream>
#include <type_traits>

template <typename T>
struct Number {
    Number(T _value = T(0)) : value(_value) {}

    template <typename S>
    Number(const Number<S>amp; n) : value(n.value) {}

    T value;

    template <typename S>
    friend Number<S> operator (const Number<S>amp; a, const Number<S>amp; b);
};

template <typename S>
Number<S> operator (const Number<S>amp; a, const Number<S>amp; b) {
    return Number<S>{a.value   b.value};
}

int main() {
    std::cout << operator <typename std::common_type<int, double>::type>(Number<int>{1}, Number<double>{1.2}).value << std::endl;
    return 0;
}
 

это реализация c 11. operator содержит ровно один аргумент. Я надеюсь, что это то, что вы хотите.