Boost logo

Boost :

From: Gennadiy Rozental (gennadiy.rozental_at_[hidden])
Date: 2006-12-15 11:49:31


"Tobias Schwinger" <tschwinger_at_[hidden]> wrote in message
news:elu6fo$ib2$1_at_sea.gmane.org...
> Gennadiy Rozental wrote:

>> 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

In part yes. But usually primary source of dependencies is not an interface,
but implementation. So in this regard usually it's more preferrable to hide
implementation to coding in generic concepts. Also STL components are not so
much an extra dependancy anyway (they are present in many/most non-trivial
translation units anyway)

> and whatever types that variant is specialized with.

tuple will depend on the same types as well.

>> 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
>> disadvantage.
>
> The bad extensibility of your proposed solution is much worse (especially
> for IO):

I don't argue that tuple based solution is much more easily extandible.

> 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.

In practive unless you are writing a generic component to be used by wide
audience, set of used types may not change that frequently
In case if I do have a lof of different types or this set is not fixed, I
would prefer header based solution either

>>>>2. It allows dynamically sized entries, so you could skip some of the
>>>>default values
>>>>3. It's as fast of could be even faster since we don't need to pass big
>>>>structures around
>>>
>>>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).

How are they wrong?

2. ...
Let's say you have record with 10 optional elements. tuple based solution
will end up compiling in anything from 1 to 10! different versions of the
same function, while offline version will be only one. Also in case if you
always want output in the same 10 column format I dont see easy way to
implement it using tuples.

3. ...
If you take tuples by value you will end up copying huge structures. If
not - the only difference I could see in an extra jump command per value, in
practice completely negligeble.

Also keep in mind that tupble based solution will create tuples in place
while variant collections could be used throughout the application as a
generic record storage.

>> 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).

Unfortunately I am not well versed in tuple/fusion interfaces. Lets say you
have comparatively expensive overloaded output operation foo. BOOST_FOREACH
solutions would look something like this (ignoring header line)

printer p( foo ) // don't remember exact syntax for the visitor definition

BOOST_FOREACH( my_v const& v, record ) {
    apply_visitor( p, v );
}

After compiler optimizations it should be equivalent to

BOOST_FOREACH( my_v const& v, record ) {
    switch( v.type){
    case 0:
        foo( *(type0*)v.data );
    ...
    case 10:
        foo( *(type10*)v.data );
   }
}

So that' why I think variant solution should be as fact (almost). If you
avoid the looping it will be even closer.

Gennadiy


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