Usefulness of std::make_pair and std::make_tuple in C++17

c++, c++17

Solution

In C++1z, is there a situation in which it is beneficial to use `std::make_pair` and `std::make_tuple` instead of using the constructors of `std::pair` and `std::tuple`?

There are always fun exceptions to every rule. What do you want to happen to `std::reference_wrapper`?

int i = 42;
auto r = std::ref(i);

pair p(i, r);                 // std::pair<int, std::reference_wrapper<int> >
auto q = std::make_pair(i,r); // std::pair<int, int&>

If you want the latter, `std::make_pair` is what you want.

Another situation cames in generic code. Let's say I have a template parameter pack that I want to turn into a tuple, would I write this?

template <typename... Ts>
auto foo(Ts... ts) {
    return std::tuple(ts...);
}

Now the intent of that code is to probably to get a `std::tuple<Ts...>` out of it, but that's not necessarily what happens. It depends on `Ts...`:

- if `Ts...` is a single object that is itself a `tuple`, you get a copy of it. That is, `foo(std::tuple{1})` gives me a `tuple<int>` rather than a `tuple<tuple<int>>`.

- if `Ts...` was a single object that is a `pair`, I get a `tuple` of those elements. That is, `foo(std::pair{1, 2})` gives me a `tuple<int, int>` rather than a `tuple<pair<int, int>>`.

In generic code, I would stay away from using CTAD for types like `tuple` because it's never clear what you're going to get. `make_tuple` doesn't have this problem. `make_tuple(tuple{1})` is a `tuple<tuple<int>>` and `make_tuple(pair{1, 2})` is a `tuple<pair<int, int>>` because that's what you asked for.

Additionally, since `std::make_pair` is a function template, you can pass that into another function template that maybe wants to do something:

foo(std::make_pair<int, int>);

This doesn't seem super useful, but somebody somewhere is using it to solve a problem - and you can't just pass `std::pair` there.

Problem

In my understanding, the sole reason for the existence of `std::make_pair` and `std::make_tuple` is that you don't have to write the types by yourself as they are automatically deduced. In C++17, we have template argument deduction for class templates, which allows us to simply write ``` std::pair p(1, 2.5); // C++17 ``` instead of ``` auto p = std::make_pair(1, 2.5); // C++11/14 ``` The situation for `std::tuple` is analogous. This leads to the following question: In C++17, is there a situation in which it is beneficial to use `std::make_pair` and `std::make_tuple` instead of using the constructors of `std::pair` and `std::tuple`? Please, consider just pure C++17 code (i.e. no need for backward compatibility with C++14) and assume that everyone is familiar with this C++17 feature.

Original source

Related problems