[Proto] lazy transform is not working

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[Proto] lazy transform is not working

Dave Jenkins-3
In the program below, I expected the proto::lazy transform to call the
times2() function, but it doesn't.  It does work correctly if you substitute
times2<int> for proto::_state.  Is this a bug or am I forgetting something?

Thanks,
Dave Jenkins

#include <iostream>
#include <boost/proto/proto.hpp>
#include <boost/proto/transform.hpp>
namespace proto = boost::proto;

template<typename T, typename Callable = proto::callable>
struct times2
{
    typedef T result_type;

    T operator()(T i) const
    {
        std::cout << "Called times2()\n";
        return i * 2;
    }
};

struct IntTimes2
    : proto::when<
        proto::terminal<proto::_>
      , proto::lazy<proto::_state(proto::_value) >
    //, proto::lazy<times2<int>(proto::_value) >
    >
{};

int main()
{
    int dummy = 0;
    proto::terminal<int>::type i = {1};
    IntTimes2()(i, times2<int>(), dummy);
}



_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Proto] lazy transform is not working

Eric Niebler-3
Dave Jenkins wrote:
> In the program below, I expected the proto::lazy transform to call the
> times2() function, but it doesn't.  It does work correctly if you
> substitute times2<int> for proto::_state.  Is this a bug or am I
> forgetting something?

A bug. It's fixed now on the trunk and release branches. Thanks.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Proto] lazy transform is not working

Dave Jenkins-3
> A bug. It's fixed now on the trunk and release branches. Thanks.

Thank you, Eric.  That works, but now proto::lazy isn't working with
proto::fold.

Below is a program you posted to boost.devel on 3/29/2008, updated with
s/bind/lazy/ and s/_arg/_child/.  It's giving me the following syntax error.
Any idea what's wrong?

Thanks,
Dave Jenkins

error C2664: 'Accumulator<IsValid,Value>::Accumulator(const
Accumulator<IsValid,Value> &)' : cannot convert parameter 1 from
'Accumulator<IsValid,Value>' to 'const Accumulator<IsValid,Value> &'
c:\boost\boost\proto\transform\call.hpp 156

#include <iostream>
#include <boost/assert.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/proto/proto.hpp>
#include <boost/proto/transform.hpp>
namespace mpl = boost::mpl;
namespace proto = boost::proto;

template<typename IsValid = mpl::true_, typename Value = void>
struct Accumulator
    : IsValid
{
    template<typename Value2>
    struct validate
        : mpl::and_<
            IsValid
          , mpl::or_<
                boost::is_void<Value>
              , boost::is_same<Value, Value2>
            >
        >
    {};

    template<typename Sig>
    struct result;

    template<typename This, typename Value2>
    struct result<This(Value2)>
    {
        typedef Accumulator<validate<Value2>, Value2> type;
    };

    template<typename Value2>
    typename result<void(Value2)>::type
        operator ()(Value2 const &) const
    {
        return typename result<void(Value2)>::type();
    }
};

struct SameTerminals
    : proto::or_<
        proto::when<
            proto::terminal<proto::_>
            // treat the current state as a callable
            // object and pass it the value of the terminal.
          , proto::lazy<proto::_state(proto::_child)>
        >
      , proto::otherwise<
            proto::fold<proto::_, proto::_state, SameTerminals>
        >
    >
{};

int main()
{
    int dummy = 0;
    proto::terminal<int>::type i = {0}, j = {1}, k = {2};
    proto::terminal<short>::type s = {42};

    BOOST_ASSERT( SameTerminals()(i+j*k, Accumulator<>(), dummy) );
    BOOST_ASSERT(!SameTerminals()(i+s*k, Accumulator<>(), dummy) );
}


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Proto] lazy transform is not working

Eric Niebler
Dave Jenkins wrote:
>> A bug. It's fixed now on the trunk and release branches. Thanks.
>
> Thank you, Eric.  That works, but now proto::lazy isn't working with
> proto::fold.
>
> Below is a program you posted to boost.devel on 3/29/2008, updated with
> s/bind/lazy/ and s/_arg/_child/.  It's giving me the following syntax
> error. Any idea what's wrong?

Yes, the new code is actually correct, but it requires you to correctly
handle references in your function object. Just add the following
result<> specializations to the Accumulator<> class template:

    template<typename This, typename Value2>
    struct result<This(Value2 &)> : result<This(Value2)>
    {};

    template<typename This, typename Value2>
    struct result<This(Value2 const &)> : result<This(Value2)>
    {};

With this change, it works for me.

--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [Proto] lazy transform is not working

Dave Jenkins-3
> With this change, it works for me.

Works for me too. Thanks.

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users