Boost logo

Boost Users :

Subject: Re: [Boost-users] BOOST_RESULT_OF_USE_DECLTYPE not default on C++11 compilers
From: Michel Morin (mimomorin_at_[hidden])
Date: 2012-01-27 04:27:20


Jeremiah Willcock wrote:
>>>> On 1/25/2012 6:42 PM, Jeremiah Willcock wrote:
>>>>> At least on GCC 4.6 in C++0x (C++11) mode, BOOST_RESULT_OF_USE_DECLTYPE
>>>>> is not set by default, preventing classes such as
>>>>> boost::transform_iterator from working on built-in lambda expressions.
<snip>
> So far I'm using a -D on the compile line to turn it on;

BOOST_RESULT_OF_USE_DECLTYPE might break some codes of Boost,
so how about wrapping a function object without tr1 result_of support into
a tr1 function object (i.e. a function object with tr1 result_of support)?
This approach enables us to use transform_iterator with C++11 lambda
without defining BOOST_RESULT_OF_USE_DECLTYPE.

I just wrote a code which wraps into a tr1 function object. Additionally,
I made wrapped functors to be DefaultConstructible and CopyAssignable.
(Since C++11 lambda is not DefaultConstructible nor CopyAssignable,
transform_iterator with it is not a "decent" iterator. Like oven::regular,
the wrapper solves this problem.)

Here is a code:
(Complete code is attached in this mail)

template <typename Func>
class tr1_functor
{
public:
    // tr1 result_of support
    template <typename Sig>
    struct result;

    template <typename This, typename... Args>
    struct result<This(Args...)>
    {
        typedef
decltype(boost::declval<This>()(boost::declval<Args>()...)) type;
    };

    // construction and assignment
        /* … */

    // invoke
    // precondition: f_ is initialized
    template <typename... Args>
    typename result<Func(Args&&...)>::type operator()(Args&&... args)
    {
        return (*f_)(static_cast<Args&&>(args)...);
    }

    // const version of operator()
    /* … */

private:
    // data
    boost::optional<Func> f_;
};

template <typename Func>
tr1_functor<Func> make_tr1_functor(Func const& f)
{
    return tr1_functor<Func>(f);
}

/* Usage */
int main (int argc, char* argv[])
{
    using boost::adaptors::transformed;

    BOOST_FOREACH(int i
      , boost::irange(0,5)
      | transformed(make_tr1_functor([](int i){ return i * 100; }))
    )
    {
        std::cout << i << " ";
    }
    // Output: "0 100 200 300 400"

    return 0;
}

Regards,
Michel




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