Boost logo

Boost Users :

Subject: Re: [Boost-users] compilation problem and a couple ofboost::variantquestions
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-07-11 20:23:13


On Wed, Jul 11, 2012 at 4:38 PM, Petros <pmamales_at_[hidden]> wrote:
[...]

> >> You mean the first type in the sequence of value types that is
> convertible from the argument? That's possible, but I don't believe
> boost::variant presently attempts to do that. You can always try!
> Or, maybe can’t [image: Winking smile]) (I really have a user’s
> knowledge/attitude to variant).
>

I meant, literally, you can just try it:

boost::variant< int, int > x(0);

[...]

> >> Hmmm...then why are you using variant?
> Because I need a single type as an output from my various templates.
> Say you are solving a PDE. And your various PDE classes contain
> (coefficient) functions of all kinds ( contstants, zeros etc.) Then I want
> to have a unique type
> as an output. A variant seemed like a good idea. The type of the function
> is known at compile time. I just don’t want to carry around O(N^2) types
> where N the dimensionality of the PDE
> - and this is just for the cross terms.
>

Hmmm...okay; have you consider boost::function?

> >>Well, variant essentially erases the type of the object it's constructed
> with, so you're effectively using runtime polymorphism (though of a more
> controlled nature than boost::any or virtual functions). I don't know
> enough
> about the particulars of your application based on your description above
> to know if that's appropriate.
> Here is a problem to understand what I am thinking of (only for info
> purposes, no purpose of cluttering you):
> Say, I have a vector Monte-Carlo engine that advances like
> V(t_dt) = m*dt * sigma*Fi*zeta*random
> where now m, sigma, Fi, zeta can be zero or one and have various classes
> that produce them. I want to have a single class for the advancement
> (actually there are various different classes dependent on the numerical
> method).
> Now, I can use expression templates for them, but there are significant
> gains if I know that certain type are fixed (say, m = 0 and/or zeta = 1 ).
> This is why I want to ba able to have these functions in a controlled
> manner (they are only a few of those, so a variant seems natutral.
> The same with a PDE example.
>

It sounds like the optimizations you're looking for are pretty application
specific. For example, if you perform runtime checks on whether some of
your factors are constant or zero to avoid recomputing some factors or
avoid computing other factors altogether, you *might* get some performance
gains in some situations but you'll probably lose performance in other
situations. It depends on whether the branching for those checks hurts you,
what the relative cost is of computing the more expensive factors, etc.

I might suggest delaying the type erasure as much as possible. For example,
set up your interface such that you package the entire expression m * dt *
sigma * Fi * zeta * random into a type-erased object (like boost::function)
and use the static types for the individual factors. I don't know if that's
possible or reasonable for your use case but it might give you some ideas.

 What I really need is some variant type that encapsulates what I described
> above. The number of calls to the subscript operator is going to be in the
> millions. (btw this is what I call opimized)
>

Every call to the subscript operator is going to have to dispatch through
the which() index to determine the underlying dynamic type of the variant.
This is likely going to be significantly slower than indexing a
std::vector. The only way to be sure is to benchmark it yourself.

[...]

> PS: No offense to anyone, but the documentation is a bit obscure. I think
> there would be a certain benefit, if in the documentation there was some
> info on implementation issues, to allow people
> to make more educated decisions.
>

That's fair; it's likely like that since the implementation is liable to
change, or vary greatly across various compilers depending on which
compilers perform best with which implementation. Ultimately, if you're to
the point where you need to know the implementation of boost::variant for
something, you'd probably have to look at the source code anyway to be sure.

> Maybe it is my fault, but after having spent some time with it, I still do
> not know what is contained in the data structure ( copies,
> references/pointers-to-external objects, who knows),
>

A boost::variant just "holds" an object of one of its value types. It's the
same idea as a union, e.g., a boost::variant< int, double > is basically
the same as

struct V
{
    union { int i; double d; } u;
    int which;
};

Or maybe instead of an index to discriminate what's in the union, a pointer
is used; that's implementation-dependent.

what are the guarantees of compile-time variant etc.
>

Actually the guarantees of boost::variant are very well documented and (I
thought) a strong point of the documentation...

- Jeff



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net