|
Boost : |
From: Eric Friedman (ebf_at_[hidden])
Date: 2003-08-10 03:09:30
Brian,
Brian Simpson wrote:
> A fundamental problem encountered by boost::variant is that of invoking an
> overloaded function for the correct type, where the type is not known
until
> runtime. As near as I can tell, all proposed solutions to this problem
have
> involved uncomfortable space or time tradeoffs. I have read several posts
> which asked why we couldn't use a switch statement--it would avoid the
> expenses of the current solutions without incurring any of its own.
> Until recently, I agreed with those (whose expertise I highly respect) who
> said it was not possible.
I don't think anyone ever said it wasn't possible. It was just whether it
would actually improve anything -- i.e., it was unclear whether compilers
would optimize recursively-inlined switch statements better than
recursively-inlined if statements.
> However, while perusing the source for the current implementation of
> boost::variant, a possible solution occurred to me.
> I have spent some time fleshing out the proposed solution, and it seems to
> be all standard C++ (no non-standard). I think it might be referred to as
> "sequence unrolling".
> Here's how it works:
[snip]
>
> Questions or comments?
Sorry, I've just gotten back from vacation. I haven't spent *too* much time
looking through your code, but I can't see how it improves on my current
code, which features sequence unrolling. If you could explain to me I'd
appreciate it.
> p.s. I must acknowledge Itay's and Eric's efforts in the current
> implementation of boost::variant. I've learned a lot just from studying
the
> code.
Thanks! It's nice to know our efforts are being recognized :)
> It was while I was browsing the recently added implementation of
> switched type selection based on the variadic template parameters that
this
> idea occurred to me.
Wait, hold on a second. The current implementation isn't tied to any
particular "unrolling constant." The current visitation mechanism after
preprocessing should like like this (see function template
apply_visitor_impl):
typedef typename step0::type T0;
typedef typename step0::next step1;
typedef typename step1::type T1;
typedef typename step1::next step2;
// ...and so on until unrolling constant...
switch (var_which)
{
case (Which::value + (0)):
return apply_visitor_impl(visitor, storage, static_cast<T0*>(0),
1L);
case (Which::value + (1)):
return apply_visitor_impl(visitor, storage, static_cast<T1*>(0),
1L);
// ...and so on until unrolling constant...
}
// ...else continue unrolling next "chunk" of types (by recursively
calling the above w/ stepN)...
Thus, if we are to assume O(1) complexity for a switch, then the complexity
of the visitation mechanism becomes O( N / unrolling-size ), where
unrolling-size is exposed as BOOST_VARIANT_APPLY_VISITOR_UNROLLING_LIMIT. I
think this is as good as it gets.
Let me know if your implementation is achieving a better result.
Thanks,
Eric
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk