C++17中std::make_pair和std::make_tuple的使用

t3irkdon  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(143)

在我的理解中,std::make_pairstd::make_tuple存在的唯一原因是你不必自己写类型,因为它们是自动推导出来的。

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

而不是

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

std::tuple的情况类似。这导致以下问题:在C17中,是否存在使用std::make_pairstd::make_tuple而不是使用std::pairstd::tuple的构造函数的情况?
请考虑纯C
17代码(即不需要向后兼容C14),并假设每个人都熟悉C17的这个特性。

y1aodyip

y1aodyip1#

在C++1z中,是否存在使用std::make_pairstd::make_tuple而不是使用std::pairstd::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>>

在泛型代码中,我会避免对tuple这样的类型使用CTAD,因为它永远不清楚你会得到什么。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

相关问题