Boost logo

Boost :

From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2007-02-28 20:18:21


On 3/1/07, Lewis Hyatt <lhyatt_at_[hidden]> wrote:
> > values. What I want is something like this:
> >
> > struct system1 : ordinal<get_next_system_ordinal()> { };
> > struct system2 : ordinal<get_next_system_ordinal()> { };
> >
> > where I don't really care what the specific order is, just that the
> > ordinal values are unique... Anyone have a bright idea on how to
> > accomplish this? Preprocessor?
>
> Hmm, I doubt you can do this with as much generality as you would like,
> especially since it would be hard to ensure uniqueness across multiple
> translation units.
>
> What about a solution like this:
>
> /////////////
>
> struct ordinal_tag {};
>
> template<class A>
> struct ordinal {
> static ordinal_tag const tag;
> template<class B>
> bool operator<(ordinal<B> const& other) {
> return &tag < &other.tag;
> }
> };
>
> template<class A>
> ordinal_tag const ordinal<A>::tag = ordinal_tag();
>
> struct system1 : ordinal<system1> {
> };
>
>
> struct system2 : ordinal<system2> {
> };
>
> struct system3 : ordinal<system3> {
> };
>

You need to actually define const static members of out of class.

You usually can get away if the member is an integral type, is static
const if you only read its _value_ (this is actually more or less
guaranteed by the standard, see this thread in comp.lang.c++:
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/d81e99be8dec94dc/d25c4150d19ea60c?lnk=gst&q=definition+outside+of+class+scope+static&rnum=6#d25c4150d19ea60c
),

unfortunately here you have a static member of an user defined type
and also its address is taken, thus no luck.

But wait, there is hope: you can do this:

////////

template<class A>
struct ordinal {
       void * tag() {
          static int const tag_;
          return &tag_;
      }
       template<class B>
       bool operator<(ordinal<B> const& other) {
               return std::less<void*>(tag(), other.tag());
       }
};

//////

This solution should also be MT safe.

> ////////////////
>
> This relies on being able to order pointers even when they don't point into the
> same array, which is technically undefined behavior.
>
> Now that I think about it, don't people use std::map<void*,T> all the time? How
> do they make sure that is portable?
>
>

Comparing pointers outside of arrays is not portable, on the other
hand std::less<T*> is required to do the RightThing.

Anyways, while pointers to static function variables are guaranteed
unique, they are not constant expressions, so this might not be what
the OP was looking for.

Anyways^2 this is probably a bit off-topic here...

gpd


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk