Instead of writing town->first
I would like to write town->name
. Inline named accessors (Renaming first and second of a map iterator and Named std::pair members) are the best solutions I have found so far. My problem with named accessors is the loss of type safety:
pair<int,double>
may refer to struct { int index; double value; }
or to struct { int population; double avg_temp; }
. Can anyone propose a simple approach, perhaps something similar to traits?
I often want to return a pair or a tuple from a function and it is quite tiring to introduce a new type like struct city { string name; int zipcode; }
and its ctor every time. I am thrilled to learn about boost and C++0x but I need a pure C++03 solution without boost.
Update
Re andrewdski's question: yes, a (hypothetical) syntax like pair<int=index, double=value>
which would create a distinct type from pair<int=population, double=avg_temp>
would meet your requirement. I do not even mind having to implement a custom pair/tuple template class ONCE and just passing a 'name traits' template argument to it approprietly when I need a new type. I have no idea how that 'name traits' would look like. Maybe it's impossible.
Although not perfect, it is possible to use tagged data:
But as Ben Voigt says:
struct city { string name; int zipcode; };
would pretty much always be better.EDIT: Templates probably are an overkill, you could use free functions in a namespace instead. This still does not solve type safety issues, as any
std::pair<T1, T2>
are the same type as any otherstd::pair<T1, T2>
:I think you should really introduce new types here. I am totally on stl's side in terms of having a pair class, but this is the exact reason why java people argue they don't want to have a pair class and you should always introduce new types for your piar-like types.
The good thing about the stl solution is that you can use the gerneric class pair, but you can introduce new types / classes whenever you really want members to be named in a different way than first/second. On top of that introducing new classes gives you the freedom of easily adding a thrid member if it should ever become necessary.
I guess elaborating on
is the closest you get to what youre looking for, althrough
struct City { string name; int zipcode; }
seems perfectly fine.You'll be happy to know that the ranges proposal also includes a something called
tagged_pair
, so that your:can also be written as:
Of course this can also be used in the return type directly as normal:
Since
std::pair
is commonly used for storing entries instd::map
containers, you might want to look at tagged elements in Boost Bimap.Synopsis:
Note that bimaps can transparently emulate
std::map
or other associative container types without performance cost; They just are more flexible. In this particular example, the definition would most likely best be changed into something like:I invite you to wander around the documentation for Boost Bimap to get the full picture
perhaps you can inherit your own pair class from pair and set two references called name and zipcode in your constructor ( just be sure to implement all constructors you will use )