Difference between pair of consts and const pair

c++, constants

Solution

The core difference is that they are different unrelated types (with some implicit conversions among them).

void f(std::pair<std::string,std::string> const &);
std::string longstring();
int main() {
   std::pair<const std::string,const std::string> pc
        = std::make_pair(longstring(),longstring());
   f(pc);
   const std::pair<std::string,std::string> cp
        = std::make_pair(longstring(),longstring());
   f(cp); 
}

While there are implicit conversions that allow `f(pc)` to compile, that line involves a conversion, and the conversion involves making a copy of the `longstring()`s. On the other hand, the call `f(cp)` only binds a constant reference to the existing pair as the type matches, not requiring any copies.

The fact that the compiler let's you write similar code, does not mean that the code is compiled to do the same thing. This is particularly true for types with implicit conversions, as is the case of `std::pair`

This is a common pitfall when writing functors to operate on elements stored in maps, where a mismatch on the argument of the functor will cause unnecessary copying of the object data:

std::map<int,std::string> m = create_map();
std::for_each(m.begin(),m.end(),
              [](std::pair<int,std::string> const &r) { 
                    std::cout << r.second << " ";
              });

The lambda above does not have the correct type of argument (`std::pair<int,std::string` vs. `std::pair<const int,std::string>`) and that causes each call to copy both the index and the value (i.e. all strings will be copied, to an `std::pair<int,std::string>` and then a reference bound for the argument to the lambda). The simple recommendation in this case would be to use `std::map<int,std::string>::value_type const &` for the argument type.

Problem

In C++, what's the difference in behavior between `std::pair<const T, const U>` and `const std::pair<T, U>`?

Original source