-2

I have overloaded operator+ in my code,

template < class T1, class T2 >
inline std::pair < T1, T2 > operator+ ( const std::pair < T1, T2 > & a, const std::pair < T1, T2 > & b )
{
    return std::make_pair < T1, T2 > ( a.first + b.first, a.second + b.second );
}

However, below fails

vector < pair < int, int > > v ( n );
accumulate ( v.begin( ), v.end( ), make_pair ( 0, 0 ) );

with the compiler complaining that

... stl_numeric.h:128:2: error: no match for 'operator+' in  ...

and forces an explicit form as below:

accumulate ( v.begin( ), v.end( ), make_pair ( 0, 0 ), operator+< int, int> );

My question: Why I need to provide operator+ explicitly?

In particular why the line below works like a charm when accumulate fails?

make_pair ( 2, 3 ) + make_pair ( 5, 7)
behzad.nouri
  • 74,723
  • 18
  • 126
  • 124
  • Out of curiosity, have you tried without templating the operator? – zneak Sep 05 '13 at 15:22
  • 3
    Probably because of dependent name lookup. The lookup in `std::accumulate` will only find an `operator+` that is declared before the definition of `std::accumulate` or in an namespace associated with its arguments (the global namespace is *not* associated with `std::pair`). – dyp Sep 05 '13 at 15:25
  • 2
    This might be a [duplicate](http://stackoverflow.com/q/4447827/420683) – dyp Sep 05 '13 at 15:26
  • [SSCCE](http://ideone.com/vo9trN). – Yakk - Adam Nevraumont Sep 05 '13 at 15:34
  • 2
    "Wrapping the overload definition with namespace std { ... } solves the issue. thanks folks." Unfortunately, this isn't a solution: [namespace.std]/1 "The behavior of a C ++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified." – dyp Sep 05 '13 at 15:35

1 Answers1

1

It seems you are defining an operator working on types defined in namespace std outside of this namespace. This makes sense because you are not allowed to overload it as general as you do in namespace std: it needs to involve at least one user-defined type to be allowed to overload it namespace std).

When templates are instantiated functions depending on a template argument are only found using argument dependent look-up. ADL only finds names in the namespaces associated with the arguments. In your example the only associated namespace is std.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • "it needs to involve at least one user-defined type to be allowed to overload it namespace `std`" Wow, that's news to me. I thought only specializations were allowed. Did this change recently? – dyp Sep 05 '13 at 15:37
  • @DyP: Specialization are only allowed *if they involve at least one user-defined type*. The rule you remember and the one Dietmar is using aren't mutually exclusive. – Ben Voigt Sep 05 '13 at 15:41
  • @BenVoigt True, but the OP's example is not a specialization. – dyp Sep 05 '13 at 15:43
  • @DyP: That's true. Overloading `std::operator+` wouldn't be allowed (or required, since an overload can go in the namespace of the user-defined type). Specializing `std::plus` would be allowed for user-defined types, but `std::accumulate` doesn't use `plus`; not sure if it would be better if it did. – Ben Voigt Sep 05 '13 at 15:48
  • @BenVoigt: You are right: a program isn't allowed to overload a function in namespace `std` because there is no need to do so: it can be overloaded in a namespace involving a yser provided type. – Dietmar Kühl Sep 05 '13 at 17:20