Why does including <utility> break structured bindings in GCC?

倾然丶 夕夏残阳落幕 提交于 2019-12-03 23:55:02
Barry

This is compiler bug 78939. Although it's a bit more complicated than that - there were a few issues between the core language and the library that were mutually contradictory (GB 20, LWG 2770, and LWG 2446), which lead to the kind of behavior that gcc/libstdc++ exhibit here. It is certainly intended that the code work with or without #include <utility>, it's just a matter of the standard wording having gotten there properly.


Yes, classes with all public non-anonymous union members should be usable in structured bindings declarations per [dcl.struct.bind]/4:

Otherwise, all of E's non-static data members shall be public direct members of E or of the same unambiguous public base class of E, E shall not have an anonymous union member, and the number of elements in the identifier-list shall be equal to the number of non-static data members of E. Designating the non-static data members of E as m0, m1, m2, ... (in declaration order), each vi is the name of an lvalue that refers to the member mi of e and whose type is cv Ti, where Ti is the declared type of that member; the referenced type is cv Ti. The lvalue is a bit-field if that member is a bit-field. [ Example:

struct S { int x1 : 2; volatile double y1; };
S f();
const auto [ x, y ] = f();

This is completely unrelated to the inclusion of <utility>, nothing in this code depends on any library functionality - the members are grabbed directly, and not via the get/tuple_size mechanism.

The core idea behind structured bindings is that std::tuple_size<T> defines how many components you get from unpacking T, and T::get<N> should access the N'th element. Not surprising, this std::tuple_size<T> is a specialization from the base template in <utility>.

Now in this case, Point doesn't have such support for structured bindings, but it is a special case (all public non-static members) for which C++17 states that no special unpacking support is needed. This is an exception to the rule above.

The compiler is tripping over itself here, and trying to use the generic rule when it sees the unspecialized std::tuple_size from <utility>.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!