From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2006-12-15 08:03:53
Gennadiy Rozental wrote:
> "Tobias Schwinger" <tschwinger_at_[hidden]> wrote in message
>>sorry for jumping in here. But I believe this post might need a bugfix.
>>Gennadiy Rozental wrote:
>>>"John Maddock" <john_at_[hidden]> wrote in message
>>>>Weapon Liu wrote:
>>>>>I personally very like this fancy facility, and that's why I present
>>>>>these mumbles here to annoy you guys( if so, my apologies go here:-))
>>>>I can give you one use I have for tuples:
>>>>I have a piece of boilerplate code that accepts a tuple (of any size) and
>>>>prints out either a csv file or a boost::array C++ code conaining the
>>>>It allows me to output data for graphing, or matrixes of test data very
>>>>quickly just by creating a short function that returns a tuple, and then
>>>>passing that function to my boilerplate. If I want more columns of data
>>>>just increase the size of tuple by 1.
>>>>I suppose I could have used a vector instead, but it's less elegant
>>>How the std::vector<boost::variant> is less elegant?
>>>1. It's could be implemented in cpp file. Your tuple based solution is in
>>Right. It can be both an advantage or an disadvantage depending on what
>>you're up to (modularity vs. genericity).
> Here is my logic:
> we should prefer to minimize dependency,
Where are we doing that? A template written towards concepts has no dependencies while a separate-translation-unit-solution depends at least on vector, variant and whatever types that variant is specialized with.
> unless performance in visibly hurt
> in performance critical area => we should prefer to place implementation in
> cpp files under the same circomstances => we were talking anout output
> operation, so performace is
> a) not that critical
> b) mostly lost in syste i/o
> => i/o operation we should prefer to implement offline
> In other words: for the problem at hand inline implementation is
The bad extensibility of your proposed solution is much worse (especially for IO):
Extending the variant requires you to touch the header (and can cause a major rebuild). It also requires you to add a switch case for the new type to the code in the cpp file. If you have a lot of "ostreamable" types (which is not too uncommon of a case), you end up with many (totally unecessary) dependencies that will cause your cpp file to be rebuilt a lot.
For the Fusion case things just work. No dependencies, no code has to be written to have things work with another type.
(Given the ostream operators exists in both cases).
>>(Sidenote: If you know how the tuples will look like you can instantiate
>>them explicitly and toast them into a cpp file, but I'd probably go for
>>vector<variant> in case I need a translation boundary for the sake of
(-; Not that it's always possible, due to combinational explosion).
> So would I
As shown above, a translation boundary doesn't always make things better, though. In fact, removing generericity can introduce much more dependencies than it eliminates.
>>>2. It allows dynamically sized entries, so you could skip some of the
>>>3. It's as fast of could be even faster since we don't need to pass big
>>AFAIK Boost.Variant calculates the storage size based on the largest
>>object (just like a union does). It also has good reason to do so since
>>heap allocation is an expensive operation.
>>IOW if we have vector< variant<some_huge_class,int,int> > and most of the
>>variants in the vector are ints we're wasting memory.
> In case like this we should be using snart_ptr<some_huge_class> instead of
> some_huge_class as a member of tuple. But for the task at hand I don't see
> this as a real problem anyway.
Well, the statements from your OP read pretty general to me (and, excuse my bluntness, these two in particular are just plainly wrong in any context).
>>>The only drawback is that you need to know set of types ahead of time.
>>>this is minor IMO and it's quite easy to add an extra type whether a need
>>Here's another drawback: Say we want to visit every entry in the sequence
>>and use an appropriate function for each type of thing we find. With
>>vector< variant<...> > we need a) a loop and b) to choose the function at
>>runtime. Both can be eliminated with Fusion and it even takes less code to
> Again. It's probably applicable for the performance critical area. For the
> output operation I would stick with BOOST_FOREACH or stl algorithm.
> In my experience performance critical tasks are comparatively rare and we
> should not blur the clarity and simplicity for no particular reason.
Yes, we shouldn't blur the clarity. The Fusion solution is simpler and cleaner (just implement both ways and you'll see).
Further you are proposing to violate the golden law of modularization: "Find modules with strong coherence and provide loose coupling among them" (so the vector<variant> solution is bad design even if Fusion didn't exist).
> P.S. please do not take these posts as a critique of the fusion lib,
> I just do not want us to be carried away by it's power.
No offense taken (why should I? I'm not even its author). In fact, I think that critique is a good thing - and so is critique to critique.
I also believe that it's important to explore the power of new libraries, rather than to run away from it.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk