On Wed, Jul 11, 2012 at 4:38 PM, Petros <pmamales@nyc.rr.com> 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
) (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