std::make_pair 和 std::make_tuple 在 C++1z 中的用处

Usefulness of std::make_pair and std::make_tuple in C++1z

在我的理解中,存在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++1z, we have template argument deduction for class templates的唯一原因,这让我们可以简单地写成

std::pair p(1, 2.5); // C++1z

而不是

auto p = std::make_pair(1, 2.5); // C++11/14

std::tuple 的情况类似。这导致以下问题:在 C++1z 中,是否存在使用 std::make_pairstd::make_tuple 而不是使用 std::pair 和 [=16 的构造函数的情况? =]?

请仅考虑纯 C++1z 代码(即不需要与 C++14 向后兼容)并假设每个人都熟悉此 C++1z 功能。

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?

每条规则总有有趣的例外。你希望 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&>

如果你想要后者,std::make_pair就是你想要的。


另一种情况出现在泛型代码中。假设我有一个模板参数包,我想把它变成一个元组,我会这样写吗?

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

现在该代码的目的可能是从中得到一个 std::tuple<Ts...>,但这并不是 必然 发生的事情。这取决于 Ts...:

  • 如果 Ts... 是一个单独的对象,它本身就是一个 tuple,您会得到它的一个副本。也就是说,foo(std::tuple{1}) 给我 tuple<int> 而不是 tuple<tuple<int>>
  • 如果 Ts... 是一个 pair 的单个对象,我会得到这些元素的 tuple。也就是说,foo(std::pair{1, 2}) 给我 tuple<int, int> 而不是 tuple<pair<int, int>>

在通用代码中,我不会将 CTAD 用于像 tuple 这样的类型,因为它永远不清楚您将获得什么。 make_tuple没有这个问题。 make_tuple(tuple{1})tuple<tuple<int>>make_tuple(pair{1, 2})tuple<pair<int, int>> 因为这就是你要的。


此外,由于 std::make_pair 是一个函数模板,您可以将其传递到另一个可能想要执行某些操作的函数模板中:

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

这似乎不是很有用,但某个地方的某个人正在使用它来解决问题 - 你不能只在那里传递 std::pair