перегрузка оператора несколькими шаблонами - PullRequest
4 голосов
/ 27 января 2011
template <class T>
class A
{
    private:
        T m_var;
    public:
        operator T () const { return m_var; }
        ........
}

template<class T, class U, class V>
const A<T> operator+ (const U& r_var1, const V& r_var2)
{ return A<T> ( (T)r_var1 + (T)r_var2 ); }

Идея состоит в том, чтобы перегрузить оператор + один раз (вместо трех) для случаев: число + A, A + число, A + A (где число имеет тип T, такой же, как m_var). Интересный случай был бы, если m_var, например, int и r_var длинные.

Любая помощь будет принята с благодарностью. Спасибо.

Ответы [ 4 ]

6 голосов
/ 27 января 2011

Обычный шаблон для достижения того, чего вы хотите, - это фактически выполнить его в обратном направлении: обеспечить неявное преобразование из T в шаблон и определить только оператор для шаблона.

template <typename T>
struct test {
   T m_var;
   test( T const & t ) : m_var(t) {}   // implicit conversion
   test& operator+=( T const & rhs ) {
      m_var += rhs.m_var;
   }
   friend test operator+( test lhs, test const & rhs ) { // *
      return lhs += rhs;
   }
};
// * friend only to allow us to define it inside the class declaration

Несколько деталей об идиоме: operator+ объявлен как друг только для того, чтобы мы могли определить свободную функцию внутри фигурных скобок класса. Это имеет некоторые преимущества, когда дело доходит до поиска компилятора, так как он будет учитывать этот оператор, только если один из аргументов уже является test.

Поскольку конструктор неявный, вызов test<int> a(0); test<int> b = a + 5; будет преобразован в эквивалент test<int> b( a + test<int>(5) ); И наоборот, если вы переключитесь на 5 + a.

operator+ реализован в терминах operator+=, в одной строке, принимая первый аргумент по значению. Если бы оператор был более сложным, он имел бы преимущество, заключающееся в предоставлении обоим операторам единой реализации.

2 голосов
/ 27 января 2011

Проблема с вашим оператором + в том, что у вас есть 3 параметра шаблона, один для типа возвращаемого значения и для приведения, но компилятор не может автоматически разрешить этот параметр.

Вы также фиксируетеЕсть несколько зол с приведениями.

Вы можете воспользоваться тем, что если вы определите operator + как свободную шаблонную функцию в вашем пространстве имен , это будет иметь эффект только для типов, определенных в этом пространстве имен.

В пределах вашего пространства имен, поэтому я определю, используя только T и U

template< typename T >
T operator+( const T & t1, const T& t2 )
{
   T t( t1 );
   t += t2; // defined within T in your namespace
   return t;
}

template< typename T, typename U >
T operator+( const T& t, const U& u )
{
    return t + T(u);
}

template< typename T, typename U >
T operator+( const U& u, const T& t )
{
   return T(u) + t;
}

a + b в общем случае не охватывается этим шаблоном, если только один из типов a и b не находится впространство имен, в котором был определен шаблон.

1 голос
/ 27 января 2011

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

Если вы не хотите неявное преобразование из T в A , тогда я просто выписал бы перегрузки. Это самый понятный код, и он совсем не длинный, если следовать шаблону перегрузки "@ to @ =":

template<class T>
struct A {
  explicit A(T);

  A& operator+=(A const &other) {
    m_var += other.m_var;
    // This could be much longer, but however long it is doesn't change
    // the length of the below overloads.
    return *this;
  }
  A& operator+=(T const &other) {
    *this += A(other);
    return *this;
  }

  friend A operator+(A a, A const &b) {
    a += b;
    return a;
  }
  friend A operator+(A a, T const &b) {
    a += A(b);
    return a;
  }
  friend A operator+(T const &a, A b) {
    b += A(a);
    return b;
  }

private:
  T m_var;
};
0 голосов
/ 27 января 2011

C ++ 0x решение

template <class T>
class A
{
    private:
        T m_var;
    public:
        operator T () const { return m_var; }
        A(T x): m_var(x){}
};

template<class T,class U, class V>
auto operator+ (const U& r_var1, const V& r_var2) -> decltype(r_var1+r_var2)
{
    return  (r_var1 + r_var2 );
}

int main(){

    A<int> a(5);
    a = a+10;
    a = 10 + a;
}

К сожалению, изменение template<class T,class U, class V> на template<class U, class V> вызывает ошибка сегментации в gcc 4.5.1.Понятия не имею почему?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...