11

Is there a simple way to make a+b work in the following example:

#include <utility>
#include <iostream>

int main ()
{
    std::pair<int, int> a=std::make_pair(1,2);
    std::pair<int, int> b=std::make_pair(3,3);
    std::pair<int, int> c = a+b;

    return 0;
}
titus
  • 5,512
  • 7
  • 25
  • 39

4 Answers4

22
template <typename T,typename U>                                                   
std::pair<T,U> operator+(const std::pair<T,U> & l,const std::pair<T,U> & r) {   
    return {l.first+r.first,l.second+r.second};                                    
}                                                                                  
int main ()                                                                        
{                                                                                  
    std::pair<int, int> a=std::make_pair(1,2);                                     
    std::pair<int, int> b=std::make_pair(3,3);                                     
    std::pair<int, int> c = a+b;                                                   

    return 0;                                                                      
}  

You can also do this with more template types to support adding two different types. Right now it supports adding pairs where the first and second are different types, but the two pairs and the return must have the same type.

If you want to make the function really versatile you could do this

template <typename T,typename U, typename V,typename W>                            
auto operator+(const std::pair<T,U> & l,const std::pair<V,W> & r)                  
-> std::pair<decltype(l.first+r.first),decltype(l.second+r.second)>                
{                                                                                  
    return {l.first+r.first,l.second+r.second};                                    
} 

In c++14 you might be able to get away with auto instead of the trailing return type, if you explicitly return a pair.

aaronman
  • 18,343
  • 7
  • 63
  • 78
  • 1
    Undefined behavior should rarely be advised especially without warnings. – Yakk - Adam Nevraumont Feb 22 '14 at 16:01
  • @Yakk where is the UB? – aaronman Feb 22 '14 at 17:25
  • 2
    Overriding operators on types in std that are not dependent on any user types? I cannot find a clause that says this is unspecified or undefined, so I may be wrong: it is, at the very least, ill advised. – Yakk - Adam Nevraumont Feb 22 '14 at 18:46
  • @Yakk ya ur right I actually remember that from the standard it has to be dependent on a UDT, but I find it hard to believe it would cause problems in this case, you could also easily roll your own `pair` class in about 30 seconds – aaronman Feb 22 '14 at 19:10
  • @Yakk-AdamNevraumont, I've tried to figure out if declaring/defining an `operator` overload that only takes built-in and `std` types is UB. The only hint that it is, is that doing stuff only with built-in and `std` types often is UB. However, an operator function is a function; you cannot declare a custom `operator+(int, int)`, but `int` is a **built-in** type. I'm fairly certian the answer is not UB. The operator is not in namespace `std` and its parameter types aren't all built-in types. I don't see how this is different from a freestanding function named `plus` instead of `operator+`. – Quirin F. Schroll Feb 03 '22 at 13:36
  • @Yakk-AdamNevraumont, https://en.cppreference.com/w/cpp/language/extending_std basically uses the code above as an example for UB, but that is because it was placed in `std`. I'm convinced that if it were UB even outside the `std` namespace, cppreference would point that out or use a different example. – Quirin F. Schroll Feb 03 '22 at 13:39
  • @Bolpat I said I may be wrong; probably am. Was 8 years ago. It remains extremely ill-advised. 1. Overloading operators outside of the namespace of a type leads to behavior that surprises most programmers, 2. Overloading std types in particular is highly likely to infect otherwise unrelated code in your project (including someone else's code you #include). – Yakk - Adam Nevraumont Feb 03 '22 at 15:29
3

You can define an override for the binary + operator, specialized for pair<int, int> parameters:

std::pair<int, int> operator +(const std::pair<int, int>& x, const std::pair<int, int>& y) {
    return std::make_pair(x.first + y.first, x.second + y.second);
}
buc
  • 6,268
  • 1
  • 34
  • 51
1

Try this code :

#include <utility>
#include <iostream>
namespace
{
    std::pair<int,int> operator+(const std::pair<int,int> &a ,const  std::pair<int,int> &b )
    {
        return std::make_pair(a.first+b.first,a.second+b.second);
    }
}

int main ()
{
    std::pair<int, int> a=std::make_pair(1,2);
    std::pair<int, int> b=std::make_pair(3,3);
    std::pair<int, int> c = a+b;

    std::cout<<c.first<<"  "<<c.second;

    return 0;
}
uchar
  • 2,552
  • 4
  • 29
  • 50
  • What is the benefit of defining the operator in a namespace? Is it to make sure it doesn't override other potential `+` operators? – Muts Apr 15 '23 at 09:59
1

yes, you can overload the operator+ like this:

#include <utility>
#include <iostream>

std::pair<int,int> operator+(const std::pair<int, int>& x, const std::pair<int, int>& y) {
    return std::make_pair(x.first+y.first, x.second+y.second);
}

int main ()
{
    std::pair<int, int> a=std::make_pair(1,2);
    std::pair<int, int> b=std::make_pair(3,3);
    std::pair<int, int> c = a+b;

    std::cout << "c= ("<<c.first<<", "<<c.second<<")"<<std::endl;

    return 0;
}

will give you this:

./a.out 
c= (4, 5)
Jörg Beyer
  • 3,631
  • 21
  • 35