Structurally Bound Aliases

129 views
Skip to first unread message

Derek Ross

unread,
Dec 4, 2016, 2:24:47 PM12/4/16
to ISO C++ Standard - Future Proposals
This idea is motivated by the problem of utilizing existing types, but with a desire to change the names of the members.

For example, say you want to use pair<int,int> as a coordinate type:


 
using coord_t = pair<int,int>;

 
This is useful because you get a bunch of stuff already implemented by the pair. However you're stuck with the 'first' and 'second' member naming.  It would be nice if we could rename 'first' to 'x' and 'second' to 'y' to make them more self-descriptive.

Maybe the structured binding syntax can be hijacked for this purpose.

I propose the following syntax:

 
 
using coord_t auto [x, y] = pair<int,int> ;  


So this means that a type alias named coord_t is created, and it has two members which are aliased to pair::first and pair::second.

This could also be used with tuples, like:

 
 
using student_t auto [firstname, lastname, age] = tuple<string, string, int>;


That's all... thanks!
Derek

Nicol Bolas

unread,
Dec 4, 2016, 2:47:10 PM12/4/16
to ISO C++ Standard - Future Proposals


On Sunday, December 4, 2016 at 2:24:47 PM UTC-5, Derek Ross wrote:
This idea is motivated by the problem of utilizing existing types, but with a desire to change the names of the members.

For example, say you want to use pair<int,int> as a coordinate type:


 
using coord_t = pair<int,int>;

 
This is useful because you get a bunch of stuff already implemented by the pair.

Um, what "stuff" are we talking about? Let's go over the features of `pair`:

* Piecewise construction from a pair of `tuple`s.
* Comparison forwarded to members.
* `get/tuple_element/tuple_size` overloads.
* `swap`.
* `make_pair`

With the exception of the first, there are C++ features that cover these, or proposals in various stages of review that provide these to user-defined types. Comparison operator generation is still on the table for C++20. There have been discussions about automatically generating `get/etc` overloads for publicly accessible "product types". `std::swap` is perfectly capable of handling swap behavior. And `make_pair` is essentially obsolete now that we have template constructor deduction.

So what exactly is it that you need from `pair<int, int>` that you couldn't get from a user-defined struct?

Let's not encourage people to use tuples as a cheap way to make user-defined types. Let's instead make normal user-defined types more feature-rich.

Derek Ross

unread,
Dec 4, 2016, 5:40:58 PM12/4/16
to ISO C++ Standard - Future Proposals


On Sunday, December 4, 2016 at 1:47:10 PM UTC-6, Nicol Bolas wrote:

So what exactly is it that you need from `pair<int, int>` that you couldn't get from a user-defined struct?

I may need any or all of it!  It's an "epic win" in a productivity sense if I can use a std::pair without reinventing a bunch of wheels that pair already implements. If I have to write functions and operators for my struct (again and again), there will be some bugs in there, which I can avoid by using std::pair.
 

Let's not encourage people to use tuples as a cheap way to make user-defined types. Let's instead make normal user-defined types more feature-rich.

I consulted my copy of TC++PL, and Bjarne thinks it's OK to use std::pair as a struct replacement. So if he's not concerned with cheap types, then probably, people shouldn't worry too much about it.


Larry Evans

unread,
Dec 4, 2016, 5:48:09 PM12/4/16
to std-pr...@isocpp.org
On 12/04/2016 01:24 PM, Derek Ross wrote:
> This idea is motivated by the problem of utilizing existing types, but
> with a desire to change the names of the members.
>
> For example, say you want to use pair<int,int> as a coordinate type:
>
> |
>
> usingcoord_t =pair<int,int>;
>
> |
>
> This is useful because you get a bunch of stuff already implemented by
> the pair. However you're stuck with the 'first' and 'second' member
> naming. It would be nice if we could rename 'first' to 'x' and 'second'
> to 'y' to make them more self-descriptive.
>
> Maybe the structured binding syntax can be hijacked for this purpose.
>
> I propose the following syntax:
>
> |
>
> usingcoord_t auto[x,y]=pair<int,int>;
>
> |
>
> So this means that a type alias named coord_t is created, and it has two
> members which are aliased to pair::first and pair::second.
>
> This could also be used with tuples, like:
>
> |
>
> usingstudent_t auto[firstname,lastname,age]=tuple<string,string,int>;
>
> |
>
> That's all... thanks!
> Derek
A related discussion about "tagged_tuple" occurred here:

https://groups.google.com/a/isocpp.org/forum/#!msg/std-proposals/pk4s49YJpUg/CgprxLydEgAJ






Nicol Bolas

unread,
Dec 4, 2016, 7:55:25 PM12/4/16
to ISO C++ Standard - Future Proposals
On Sunday, December 4, 2016 at 5:40:58 PM UTC-5, Derek Ross wrote:
On Sunday, December 4, 2016 at 1:47:10 PM UTC-6, Nicol Bolas wrote:

So what exactly is it that you need from `pair<int, int>` that you couldn't get from a user-defined struct?

I may need any or all of it!  It's an "epic win" in a productivity sense if I can use a std::pair without reinventing a bunch of wheels that pair already implements. If I have to write functions and operators for my struct (again and again), there will be some bugs in there, which I can avoid by using std::pair.

OK, let's look at your example:


using coord_t = pair<int,int>;

You have a type which is a coordinate. If you were writing this type from scratch, there are many things from `pair` you wouldn't add. Not because they're time consuming, but because they're not appropriate for `coord_t`.

For example, what good is the piecewise constructor for `pair` in this case? Do you honestly expect users to pass two tuples when creating a `coord_t`? No; it's a pointless interface. It adds nothing useful to the type.

But there are worse issues in this regard. Take the less/greater comparison operators. It makes absolutely no sense to even ask the question of whether one `coord_t` is less than another. Yet your `pair`-based object provides exactly that. This is not just confusing to the user; it is actively dangerous. It gives the impression that it is reasonable to order `coord_t` objects, when it probably isn't. And even if it is, do you really want them ordered this way? Or do you want to order them in some other way?

So at best, what you've done is made a type that has a poor interface, one with more functions than is actually needed. At worse, you've made a type that has a misleading interface.

Whereas given the various proposals for automatic "product type" and equality operator generation, you would get a far better object with a better interface, just by doing this:

struct coord_t {int x; int y;};

Let's not encourage people to use tuples as a cheap way to make user-defined types. Let's instead make normal user-defined types more feature-rich.

I consulted my copy of TC++PL, and Bjarne thinks it's OK to use std::pair as a struct replacement. So if he's not concerned with cheap types, then probably, people shouldn't worry too much about it.

Bjarne also thinks that the template induction syntax in Concepts TS is a good thing too. Bjarne has good ideas, but that doesn't mean his word should be considered definitive.

Thiago Macieira

unread,
Dec 5, 2016, 4:19:16 PM12/5/16
to std-pr...@isocpp.org
Em domingo, 4 de dezembro de 2016, às 11:24:46 PST, Derek Ross escreveu:
> This idea is motivated by the problem of utilizing existing types, but with
> a desire to change the names of the members.
>
> For example, say you want to use pair<int,int> as a coordinate type:
>
>
> using coord_t = pair<int,int>;

Can you give an example that doesn't use pair or tuple?

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

Derek Ross

unread,
Dec 5, 2016, 5:24:33 PM12/5/16
to ISO C++ Standard - Future Proposals
 
Can you give an example that doesn't use pair or tuple?

You might want to convert the elements of an array into named fields, like: 

   char rawbuffer[4] = {41,42,43,44};    
   
auto [ stx, type, data, etx ] = rawbuffer;

Thiago Macieira

unread,
Dec 5, 2016, 6:52:39 PM12/5/16
to std-pr...@isocpp.org
This should work with structured bindings, provided there's a get<N> for
char[].

But this example didn't use your "using" proposal.

Let me be more specific: do you see this used with anything besides pair,
tuple, and trivial types?

Derek Ross

unread,
Dec 5, 2016, 8:04:36 PM12/5/16
to ISO C++ Standard - Future Proposals

Let me be more specific: do you see this used with anything besides pair,
tuple, and trivial types?

My personal motivation is to provide a way of "renaming" the elements of pairs and tuples, so it's easy to create structs that have the various features of pair/tuple. But it could be used anywhere where structured bindings are.


 

Daniel Boles

unread,
Dec 5, 2016, 8:16:41 PM12/5/16
to std-pr...@isocpp.org
I feel like this is really circular:
* Person doesn't want to continually write structs with the same  
methods
* Person users an extremely generic type
* Person is annoyed at how generic the type is
* Person tries to add scaffolding to make the type look like a struct
* Person says that structs could learn from the generic type

At a certain point, we just need to calm down, and use a struct.

Nicol Bolas

unread,
Dec 6, 2016, 4:33:11 PM12/6/16
to ISO C++ Standard - Future Proposals

Not only that, there is every chance that we'll be able to give a type most of the features of `pair` and `tuple` with minimal or zero effort. So as C++ becomes a better language, there will be less need for such a feature.
Reply all
Reply to author
Forward
0 new messages