为什么std::pair<A,B>和std::tuple<A,B>不同?(真的没有办法吗?)

14
为什么std::pair<A,B>std::tuple<A,B>不同?我一直觉得用一个替代另一个很奇怪。它们在某种程度上是可转换的,但有限制。
我知道std::pair<A,B>必须有两个数据成员A firstB second,所以它不能仅仅是std::tuple<A,B>的类型别名。但我直觉上认为我们可以专门针对恰好包含两个元素的元组,在定义上等同于标准要求std::pair的定义。然后将其别名为std::pair
我猜这似乎不可能,因为这太直截了当了,肯定已经被想过了,例如g++的libstdc++库中并没有这样做(我没有查看其他库的源代码)。这个定义的问题是什么?它只是会破坏标准库的二进制兼容性吗?

3
现代的 tuple 实现不是递归的。 - Columbo
2
@leemes 如果你想要一个“pair”,就将你的东西声明为“pair”。如果你想保持更通用的东西,你无论如何都不能使用“first”和“second”。也就是说,所有这些有什么用呢? - Columbo
1
@leemes,你的草图无法编译,如果你没有注意到的话。任何类似的情况都会使从tuple<Ts...>进行模板参数推导变得不可能。 - T.C.
2
std::pair 已经成为 C++98 的一部分,std::tuple(但没有可变参数模板)随后出现在 TR1 中。当时由于几个原因,将具有 2 个元素的 tuple 别名为 pair 是不可能的。模板别名和可变参数模板是 C++11 引入的。即使有了这些,也不能将 pairtuple 的特化合并,否则会破坏一些现有代码。 - koraxkorakos
1
TR1的“tuple”和C++11的“tuple”没有必须是相同的东西-这就是TR1的全部意义。 - Puppy
显示剩余11条评论
3个回答

3

在处理SFINAE和重载等问题时,需要非常小心。例如,下面的代码目前是符合规范的,但你可能会使其非法:

void f(std::pair<int, int>);
void f(std::tuple<int, int>);

目前,我可以通过重载分辨、SFINAE、模板特化等方式区分对和元组。如果将它们变成相同的东西,这些工具都将无法区分它们。这将破坏现有的代码。

或许在C++11中引入它是一个机会,但现在肯定不行了。


这个答案最容易理解了--你解释了如果我们现在改变它,兼容性将会被破坏。我想在C++11中引入一个元组是可能的,当有两个元素时是与pair兼容的(就像我描述的那样)。 - leemes

2

这纯粹是历史性的。 std::pair 自 C++98 以来就存在,而 tuple 则是后来才出现的,并且最初并不是标准的一部分。

向后兼容性是 C++ 发展中最大的负担,阻碍了一些好东西的轻松实现!


0

我还没有尝试过这个,现在也没有时间去做。你可以尝试从sd::pair派生出std::tuple的特化版本。请有人告诉我这不会起作用或者是一个特别糟糕的想法。我怀疑你会在访问器方面遇到麻烦。


你只能为自己的类专门化 std:: 模板,而不能一般性地进行专门化。 - MSalters
如果我可以专门化自己的类,我也可以专门化std类。我不明白你的推理。说实话,我不确定这很重要,如果你不回复我也不会生气。 - Nicole
这在标准中明确被禁止,没有涉及到任何理由(实际上是有原因的;如果可以的话,它将使标准库的实现变得复杂)。 - MSalters

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