结构化绑定以替换std :: tie滥用 [英] Structured binding to replace std::tie abuse
问题描述
在阅读此摘要c ++ 17的最终功能让我对结构化绑定(强调我的)这一部分感到有些惊讶:
结构化绑定
到目前为止,有一个已知的技巧可以滥用std :: tie直接将元组或对分配给不同的变量,而不必手动处理结果类型. 这是一个黑客,而且变量也必须存在,现在您可以声明变量并将其初始化为一行:
auto [a,b,c] = getvalues();
需要大括号,getvalues返回一个元组.提案中未提及std :: pair,因此尚不清楚它是否适用于pair,这是STL在某些插入方法中返回的.
我假设他们指的是std::tie
int a,b,c;
std::tie(a,b,c) = std::make_tuple(1,2,3);
我认为这是推荐做法.
有人可以解释为什么他们将上述示例称为黑客吗?
我可以这样简单地说:
在一种语言中,函数只能返回一个变量
int a,b,c;
std::tie(a,b,c) = function_returning_multiple_values();
是针对以下情况的黑客手段:
auto [a, b, c] = function_returning_multiple_values();
就像在C ++只允许一个函数参数的假设世界中一样
int p1, p2, p3;
p1 = ...;
p2 = ...;
p3 = ...;
function_taking_multiple_params(std::tie_params(p1, p2, p3));
将成为以下用途的黑客
function_taking_multiple_params(p1, p2, p3)
您非常习惯C ++限制,因此一个函数最多可以返回一个对象,但是实际上,这只是一种人工语言限制,就像接受最多一个参数的限制就是一种人工语言限制一样./p>
std::tie
是缺少语言功能的库黑客.而且它有一些缺点:
- 变量需要事先声明
- 必须明确声明变量类型
- 效率低下或不能与默认不可构造的类型一起使用
结构化绑定是否本来可以做的一切?不,但是在大多数情况下,它们是我们所需要的.
缺少什么?
- 某些元素的显式类型:例如:
auto [a, std::string b, c] = foo();
其中a
和c
具有推论的类型,而b
是显式的"std :: string"
- 嵌套.例如:
auto [a, [b1, b2], c] = foo();
其中从foo
返回的第二个对象是类似tuple
的对象.
- 返回站点的语言功能(一起绕过
std::tuple
):
auto foo() -> [int, int]
代替
auto foo() -> std::tuple<int, int>
- 命名返回对象
auto foo() -> [int& key, int& value]
...好吧...那不是很好
- 并将其与...结合-准备一个很酷的新名称-通用返回初始化:
auto minmax_element(It begin, It end) -> [It min_it, It max_it];
auto [min = *min_it, max = *max_it] = minmax_element(...);
In reading this summary of the c++17 final features I was a bit surprised by the section on structured bindings (emphasis mine):
structured bindings
Until now, there was a known trick to abuse std::tie to assign a tuple or pair to different variables directly, instead of having to deal with the result type manually. This was a hack, and also the variables had to exist, now you can declare the variables and initialize them in one line:
auto [a , b , c] = getvalues();
The braces are needed, getvalues returns a tuple. std::pair is not mentioned in the proposal, so its unclear if this works with pair, which is returned by the STL in some insert methods.
I am assuming they refer to this kind of usage of std::tie
int a,b,c;
std::tie(a,b,c) = std::make_tuple(1,2,3);
which I believed to be a recommended practice.
Can someone offer an explanation as to why they are referring to above example as a hack?
I can put it simply like that:
In a language where functions can return just one variable
int a,b,c;
std::tie(a,b,c) = function_returning_multiple_values();
is a hack for:
auto [a, b, c] = function_returning_multiple_values();
just as in the hypothetical world where C++ would allow just one parameter for functions
int p1, p2, p3;
p1 = ...;
p2 = ...;
p3 = ...;
function_taking_multiple_params(std::tie_params(p1, p2, p3));
would be a hack for:
function_taking_multiple_params(p1, p2, p3)
You are so accustomed with the C++ restriction that a function can return at most one object, but in fact it is just an artificial language restriction, just as a restriction to accept at most one parameter would be an artificial language restriction.
The std::tie
is a library hack for a missing language feature. And it has some drawbacks:
- the variables need be declared beforehand
- the variable types must be declared explicitly
- Inefficient or can't be used with types that are not default constructible
Are structured bindings everything that they could have been? No, but for the most cases they are everything we need.
What is missing?
- Explicit type for some elements: e.g.:
auto [a, std::string b, c] = foo();
where a
and c
have the type deduced and b
is explicit "std::string"
- Nesting. E.g.:
auto [a, [b1, b2], c] = foo();
where the second returned object from foo
is a tuple
like object.
- Language feature at the return site (bypassing
std::tuple
all together):
auto foo() -> [int, int]
instead of
auto foo() -> std::tuple<int, int>
- Named return objects
auto foo() -> [int& key, int& value]
... well... wouldn't that be nice
- and combine that with... - get ready for a cool new name - Generalized return initialization:
auto minmax_element(It begin, It end) -> [It min_it, It max_it];
auto [min = *min_it, max = *max_it] = minmax_element(...);
这篇关于结构化绑定以替换std :: tie滥用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!