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_pair
和 std::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
。
在我的理解中,存在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_pair
和 std::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
andstd::make_tuple
instead of using the constructors ofstd::pair
andstd::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
。