operator[]
in std::map
has the difference that in the standard it is defined as returning (*((insert(make_pair(x, T()))).first)).second
, whereas in the STL m[k]
is defined as equivalent to (*((m.insert(value_type(k, data_type()))).first)).second
.
The difference is that conforming C++ implementations call make_pair
whereas the STL constructs the pair directly. I can think of two differences this makes:
1) The standard permits an additional copy of the pair (and hence of the key and data objects), if RVO fails to kick in for the call to make_pair
. As I read it, the STL does not permit this copy (although there is of course a further copy down the line, in insert
). This matters if either the key or the value type have copy constructors with observable side-effects.
2) Users can specialize either std::make_pair
or std::pair
. If they specialize make_pair
then their code is guaranteed to be called in standard C++, and guaranteed not to be called in the STL.
Such specializations cause UB if they don't satisfy the requirements of the template, though, and in the case of make_pair
I think that if it has any observable effects other than those of creating the pair, then it doesn't satisfy the requirements. So it might be difficult or impossible in this case to write a specialization that's guaranteed to let you work out whether it has been called or not. In practice if the implementation has done the obvious thing and used the code from the standard, then you will easily see a difference...
Users can also ADL-overload make_pair
, same caveat, with the extra complication that I'm never quite sure whether mentions in the standard of unqualified function calls require that the implementation make the same unqualified call. I'm sure I've heard that some implementations have made fully-qualified calls to std::whatever
in such cases, perhaps erroneously.
Is this the sort of thing you're after?