Overloading an operator with multiple patterns

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

The idea is to overload the + operator once (instead of three) for the cases: number + A, number A +, A + A (where the number is of type T, the same as m_var). An interesting case would be if m_var is, for example, int and r_var are long.

Any help would be greatly appreciated. Thanks.

+4
source share
4 answers

The general pattern to achieve what you want is to actually execute it in the opposite direction: provide an implicit conversion from T to a pattern and define only the operator for the pattern.

 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 

A few details about the idiom: operator+ declared as a friend just to allow us to define a free function inside the curly braces of the class. This has some advantages when it comes to looking for a compiler, as it will only consider this operator if one of the arguments is already test .

Since the constructor is implicit, call test<int> a(0); test<int> b = a + 5; test<int> a(0); test<int> b = a + 5; will be converted to the equivalent of test<int> b( a + test<int>(5) ); And vice versa, if you switch to 5 + a .

operator+ is implemented in terms of operator+= , in a single line, taking the first argument by value. If the operator were more complex, this would have the advantage of providing both operators the same implementation.

+6
source

The problem with your + operator is that you have 3 template parameters: one for the return type, as well as for the translation, but the compiler cannot automatically solve this parameter.

You also commit several evils there with ghosts.

You can take advantage of the fact that if you define the + operator as a free template function in the namespace , this will only have effect on the types defined in this namespace.

Within your namespace, I define using only T and 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 does not apply to this pattern at all, unless one of the types a and b is in the namespace where the pattern was defined.

+2
source

You should not overload op + for unrelated types that you know nothing about - this could completely break working code that already exists. You must include at least one of the options in op + overload.

If you do not want the implicit conversion from T to A <T>, then I will just write overloads. This is the cleanest code, and it is not long if you follow the "@to @ =" overload pattern:

 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; }; 
+1
source

C ++ 0x solution

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

Unfortunately, changing template<class T,class U, class V> to template<class U, class V> causes a segmentation error in gcc 4.5.1. I have no idea why?

0
source

Source: https://habr.com/ru/post/1337289/


All Articles