Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2003-11-03 19:43:35


> Eric Friedman <ebf_at_[hidden]> writes:
> > No offense, but I believe it is a *terrible* idea for any type to have
> > the dual meanings of 'type sequence' and 'value type'. I've raised
> > this before; see [relevent bits of URL inline-expanded]
> >
> > > typedef mpl::list<int, std::string> some_types;
> > > typedef boost::tuple<int, std::string> some_tuple;
> > >
> > > typedef boost::variant<some_types> v1; // ok, unambiguous
> > > typedef boost::variant<some_tuple> v2; // ambiguity!?
> > >
> > > It seems clear that objects of type v1 should behave equivalently to
> > > boost::variant<int, std::string>. However, if boost::tuple were an MPL
> > > sequence, it seems less clear whether objects of type v2 should behave
> > > likewise or instead as a variant holding a 2-tuple.
> >
> > As always, please feel to tell me if/why I'm wrong.

On Mon, Nov 03, 2003 at 01:42:33PM -1000, David Abrahams wrote:
> I understand your argument, but I'm uneasy about the idea that certain
> Concepts are ineligible for multiple-refinement. IOW: why are type
> sequences special?

I'm not sure that I quite understand everything you guys are talking
about here. To clarify: here's my understanding, and point out
if/where I'm going astray...

(1)
Variant has two "interfaces", in the sense that you can say
   variant<T1,T2,T3,...Tn>
or
   variant<mpl_seq>
to mean the same thing (construct a variant type from a list of types).
This creates a "potential ambiguity" in that
   variant<A>
could be interpreted as the first kind of variant (where n=1) or the
second kind (where A is an MPL type sequence).

(2)
Tuples are (or maybe not yet are, but are proposed to be) models of the
MPL type sequence concept. As a result,
   tuple<int,string>
can be used both as "a type" and as "a type sequence". This creates a
"potential ambiguity" in that you aren't sure what "role" the tuple is
playing without any context.

(3)
The "problem" is that the two "potential ambiguities" crash into each
other and create a "real ambiguity" in this instance:
   variant< tuple<int,string> >
We might interpret this as a variant of 1 alterative (a tuple), or a
variant of two alternatives (an int or a string), depending either on
which "variant constructor" or which "tuple role" we consider.

Ok so far?

So it seems to me that "both sides" are contributing to the "problem".
The possible resolutions I see then are

(1) "variant backs down"
Under this resolution, we can no longer say
   variant<mpl_seq>
as this will always be interpreted as
   variant<T>
that is, a variant with a single alternative of type T. In order to
create a variant from an MPL sequence, you need to use alternative
syntax, such as
   variant_from_mpl_type_sequence<mpl_seq>::type
or something.

(2) "tuple backs down"
Under this resolution, a tuple is not implicitly a model of the MPL
type sequence concept. Thus we must say something explicit, like
   as_type_sequence<some_tuple>::type
or something to "get the type sequence out of the tuple".

(3) "Neither backs down"
Under this resolution, this code
   variant< tuple<int,string> >
is ambiguous. This resolution only seems reasonable to me if this
ambiguity can be detected at compile-time and create a useful
diagnostic. (As a result, you still will need a way for clients to
then disambiguate things to do what they mean.)

(4) "Both back down"
The union of resolutions (1) and (2).

Are those all of the alternatives? If so, which is best?

Apologies for using "back down" and other "adversarial" language; it was
just the first words that sprung to my mind.

(As a final aside, it seems to me that the problem here is roughly
analogous to the "problem" in this code:

   struct Bar {...}; // models BarConcept
   struct Foo {
      operator Bar() {...}
   };

   void f( Foo f ) {...}
   template <class Bar>
   enable_if<isa_BarConcept<Bar>,void>::type f( Bar b ) {...}

   Foo foo; ... f(foo); // which f()?
   // This code isn't actually ambiguous, owing to various useful C++
   // rules. Ok; the example is just meant to illustrate the analogy.

Let "Bar" = "MPL type sequence" and "Foo" = "tuple" and "f" =
"variant<...>" to complete the analogy.)

-- 
-Brian McNamara (lorgon_at_[hidden])

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