在 API 设计中,什么时候我应该更喜欢长度为 2 std::tuple 而不是一对?
In API design, when should I prefer a length-2 std::tuple over a pair?
我正在编写一个小型库,其中有一些 API 函数返回两个东西(不同类型)。我宁愿不为此声明一个结构;所以我正在考虑返回 std::pair<foo, bat>
。但是 - 也许在现代我应该更喜欢返回 std::tuple<foo, bar>
而不是?
更一般地说,什么时候元组应该优先于元组,什么时候元组更合适?
But - perhaps in these modern times I should prefer returning std::tuple<foo, bar>
instead?
More generally, when should a tuple be prefered over a pair, and when is pair the more appropriate construct?
好吧,如果您想使用(元)算法而不是 std::pair
而不是 std::pair
。
,它可能会很有用
最后,这完全取决于您的实际用例,不知道就无法回答。
如果您遇到的情况可以保证在本质上匹配一对类型(在上下文中语义相关),您最好使用 std::pair
来反映 API 中的那些语义。
如果您不确定,请使用 std::tuple
来保持 API 设计的未来灵活性。
另一种方法是简单地使用您自己的结构,这些结构清楚地为值命名语义:
template<typename T>
struct point2D {
T x;
T y;
};
template<typename T>
struct point3D {
T x;
T y;
T z;
};
template<typename Key, typename Value>
struct Item {
Key key:
Value value;
};
而不是 std::tuple<T,T>
、std::pair<T,T>
或 std::tuple<T,T,T>
元组用于包装多个值,这些值之间可能有关系,也可能没有关系。
成对用于环绕两对值,这些值彼此之间存在关系,例如。一个键值对将有两个值,一个是键,另一个是值,它们彼此有关系,例如。在哈希图中,其中键指向对或值。
它真的取决于你希望一切如何工作等等。
我经常看到正确的 API 调用或库(与数学相关)return 结构或 class 即使容器有两个值。
但如果必须的话,我同意@Bauss,如果值是键值对,则使用std::pair
,例如"table id, string name"。
但是如果元组不是键值但都是实际值例如位置是 XY 坐标 (int x, int y) 使用 std::tuple
.
警告:以下是个人观点:
在计算机科学中,只有三个有趣的数字:
- 零
- 一个
- N
因为我们要么处理某物、某物或某物的缺失。例如 average(a0 , a1)
是 average(a0, ...aI)
的特例,其中 I 是集合中的每个整数 (0 <= I < N)。
因此 std::pair
在逻辑上是 N 元组的特殊化,因此不需要。
更糟糕的是,使用 pair
假定项目数始终为 2,并将其烘焙到界面中。这显然是一个错误,因为我们正在用未来进行非破坏性更改的能力换取零收益。
第一次编写 STL 时,没有可变参数模板,只有三个成对用例:-
作为 equal_range
等的范围
作为从 map::insert
和
返回的状态迭代器
作为 map
中的 key/value 对。
然后 boost 伴随着元组等现代思想而来。作为一个非官方库,boost 能够模拟带有自动生成重载页面的可变参数模板。在每个编译器附带的标准化 API 中,这是不可想象的。
现在我们有了可变参数模板。除了不幸地融入地图界面之外,没有任何理由比 tuple
更喜欢 pair
您应该为此声明一个结构。
get<0>(x)
和 get<1>(x)
,甚至 post-C++11 的 get<Foo>(x)
和 get<Bar>(x)
,意义不大 and/or 惯用语比 x.foo
或 x.bar
.
tuple
s 最适合按顺序标识的非统一类型的事物。
pair
s 是在 C++11 之前编写的 tuple
。
pair
和 tuple
(以及 array
,而我们正在使用)都是元组类的,因为它们支持 std::tuple_size
和 get<N>
.
许多类型使用 pair
而不是具有正确命名字段的结构,这被认为是 std
库中的一个错误。即,如果map
使用struct KV{ Key key; Value value; }
,那就更好了。
现在,元编程支持 KV
作为通用对也很好。因此,tuple_size
和 get<0>
等。但是丢弃命名字段通常不是一个好主意。名字有力量。
在 C++17 中,简单的 struct
s 开始使用结构化绑定,即使您不使用它们 "tuple-like".
如果你确实有一些东西的身份是由它们的非统一类型的顺序决定的,tuple
是可行的方法。 pair
几乎是遗留类型。 pair
比 tuple
有一些优势,但 tuple
继续改进以删除它们(如 tuple
的隐式初始化)。
我正在编写一个小型库,其中有一些 API 函数返回两个东西(不同类型)。我宁愿不为此声明一个结构;所以我正在考虑返回 std::pair<foo, bat>
。但是 - 也许在现代我应该更喜欢返回 std::tuple<foo, bar>
而不是?
更一般地说,什么时候元组应该优先于元组,什么时候元组更合适?
But - perhaps in these modern times I should prefer returning
std::tuple<foo, bar>
instead?More generally, when should a tuple be prefered over a pair, and when is pair the more appropriate construct?
好吧,如果您想使用(元)算法而不是 std::pair
而不是 std::pair
。
最后,这完全取决于您的实际用例,不知道就无法回答。
如果您遇到的情况可以保证在本质上匹配一对类型(在上下文中语义相关),您最好使用 std::pair
来反映 API 中的那些语义。
如果您不确定,请使用 std::tuple
来保持 API 设计的未来灵活性。
另一种方法是简单地使用您自己的结构,这些结构清楚地为值命名语义:
template<typename T>
struct point2D {
T x;
T y;
};
template<typename T>
struct point3D {
T x;
T y;
T z;
};
template<typename Key, typename Value>
struct Item {
Key key:
Value value;
};
而不是 std::tuple<T,T>
、std::pair<T,T>
或 std::tuple<T,T,T>
元组用于包装多个值,这些值之间可能有关系,也可能没有关系。
成对用于环绕两对值,这些值彼此之间存在关系,例如。一个键值对将有两个值,一个是键,另一个是值,它们彼此有关系,例如。在哈希图中,其中键指向对或值。
它真的取决于你希望一切如何工作等等。
我经常看到正确的 API 调用或库(与数学相关)return 结构或 class 即使容器有两个值。
但如果必须的话,我同意@Bauss,如果值是键值对,则使用std::pair
,例如"table id, string name"。
但是如果元组不是键值但都是实际值例如位置是 XY 坐标 (int x, int y) 使用 std::tuple
.
警告:以下是个人观点:
在计算机科学中,只有三个有趣的数字:
- 零
- 一个
- N
因为我们要么处理某物、某物或某物的缺失。例如 average(a0 , a1)
是 average(a0, ...aI)
的特例,其中 I 是集合中的每个整数 (0 <= I < N)。
因此 std::pair
在逻辑上是 N 元组的特殊化,因此不需要。
更糟糕的是,使用 pair
假定项目数始终为 2,并将其烘焙到界面中。这显然是一个错误,因为我们正在用未来进行非破坏性更改的能力换取零收益。
第一次编写 STL 时,没有可变参数模板,只有三个成对用例:-
作为
equal_range
等的范围作为从
map::insert
和 返回的状态迭代器
作为
map
中的 key/value 对。
然后 boost 伴随着元组等现代思想而来。作为一个非官方库,boost 能够模拟带有自动生成重载页面的可变参数模板。在每个编译器附带的标准化 API 中,这是不可想象的。
现在我们有了可变参数模板。除了不幸地融入地图界面之外,没有任何理由比 tuple
pair
您应该为此声明一个结构。
get<0>(x)
和 get<1>(x)
,甚至 post-C++11 的 get<Foo>(x)
和 get<Bar>(x)
,意义不大 and/or 惯用语比 x.foo
或 x.bar
.
tuple
s 最适合按顺序标识的非统一类型的事物。
pair
s 是在 C++11 之前编写的 tuple
。
pair
和 tuple
(以及 array
,而我们正在使用)都是元组类的,因为它们支持 std::tuple_size
和 get<N>
.
许多类型使用 pair
而不是具有正确命名字段的结构,这被认为是 std
库中的一个错误。即,如果map
使用struct KV{ Key key; Value value; }
,那就更好了。
现在,元编程支持 KV
作为通用对也很好。因此,tuple_size
和 get<0>
等。但是丢弃命名字段通常不是一个好主意。名字有力量。
在 C++17 中,简单的 struct
s 开始使用结构化绑定,即使您不使用它们 "tuple-like".
如果你确实有一些东西的身份是由它们的非统一类型的顺序决定的,tuple
是可行的方法。 pair
几乎是遗留类型。 pair
比 tuple
有一些优势,但 tuple
继续改进以删除它们(如 tuple
的隐式初始化)。