Boost logo

Boost :

Subject: Re: [boost] VC10 config - some regressions in several libraries
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2010-04-29 10:59:59


On 26/04/2010 21:19, Stephan T. Lavavej wrote:
> Writing code that works under rvalue references v1 and v2
> simultaneously is generally easy. In particular, the move semantics
> and perfect forwarding idioms are unaffected. However, extreme
> caution must be used when reimplementing std::move() and
> std::forward().

I general I found both approaches similar but I can't port the following
to v2. For "emplace" functions, is more efficient in terms of code size,
to catch all references and pack them in a polymorphic class and so that
the same binary code could be used for value all non value-constructing
code. I imagine there are similar use cases for std::function or bind,
where we want to catch all input parameters by reference and use them later.

This was possible with v1 just storing some "T &&member_x" members in a
class using forward (at least in gcc 4.3). However, I can't achieve this
with VC 10 (I haven't tested gcc 4.5), because the compiler complains
(it's surely right) about warning C4413. Here's the code (a simplified
"emplace" function):

//store_and_forward_func takes a Target type, catches all references,
//packs them in store_and_forward class, and calls a deferred call
//using the stored arguments:

class int_holder
{
    int _i;
    public:
    int_holder(const int &i)
    { _i = i; }

    int_holder(int &&i)
    { _i = i; i = 0;}

    void func(){}
};

template<class Target, class Arg>
struct store_and_forward
{
    Arg &&ref; //Stores a reference for further forwarding
    store_and_forward(Arg &&r)
       //warning C4413: reference member is initialized to a temporary
       //that doesn't persist after the constructor exits
       : ref(static_cast<Arg&&>(r))
    {
       //No warning with the same cast!
       //Correct binding
       Arg&& a = static_cast<Arg&&>(r);
    }

    void call()
    {
       Target a(static_cast<Arg&&>(ref));
       a.func();
    }
};

template<class Target, class Arg>
void store_and_forward_func(Arg &&r)
{
    struct store_and_forward<int_holder, Arg> fwd(static_cast<Arg&&>(r));
    fwd.call();
}

int main ()
{
    //This should lead to a compilation error
    const int & cref = 1;
    //Ok
    store_and_forward_func<int_holder>(cref);
    //Bad forwarding, member reference is not bound
    //to the temporary int(6)
    store_and_forward_func<int_holder>(int(6));
    return 0;
}

A very similar code was possible with v1, but I can't get it work for v2.

Best,

Ion


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