C++17中std::make_pair和std::make_tuple的实用性

28
在我看来,std::make_pairstd::make_tuple存在的唯一原因是你不必自己写类型,因为它们会被自动推导。在C++17中,我们有类模板的模板参数推导,使我们可以简单地编写:
std::pair p(1, 2.5); // C++17

替代

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

std::tuple的情况是类似的。这引发了以下问题:在C++17中,是否存在一种情况,使用std::pairstd::tuple的构造函数而不是使用std::make_pairstd::make_tuple会更有优势呢?

请考虑纯C++17代码(即不需要与C++14向后兼容),并假设每个人都熟悉这个C++17特性。


15
“Analogical”也是我即将发布的《瓦肯人》成人同人小说的标题。非常迷人。 - Kerrek SB
std::make_pairstd::reference_wrapper<T>衰减为T&。推导指南是否考虑到了这一点? - DeiDei
我认为(但不确定)在涉及std :: reference_wrapper时,构造函数和make_pair之间存在差异。 - Kerrek SB
3
抱歉我毁了你的笑话 :) - Barry
@KerrekSB 哦,我现在才明白,20分钟后... - DeiDei
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
45
在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


1
std::reference_wrapper 类似,您可以添加 make_pair 重载(使用自定义类型),而无需完全专门化 pair 以适应您的类型。 - Jarod42
@KerrekSB 我不认为这与此相关?direct_init<T>tupple上无法工作(除非T具有tupple构造函数)。 - Barry
@Barry: 如果你想要一个语言参考,为什么不只是使用pair p(i, *r);呢?确实,这会比使用make_pair示例更清晰地表达你的意图。我本来也期望它会使用reference_wrapper - Nicol Bolas
2
@NicolBolas 不,那会给您 pair<int,int> (假设您的意思是像 r.get() 一样)。 - Barry
1
@KyleStrand 我在“需要使用auto”这里停下了。那...并不正确。 - T.C.
显示剩余13条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,