Boost logo

Boost :

Subject: [boost] [proto] lazy functions in custom domains
From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2009-02-23 04:32:36


Hi Guys,

I've recently tried to play around with Boost.Proto and I think I've
run into a wall. I was trying to figure this (relatively simple) case
out for a while already but it I'm at my wits end not seeing why the
implementation doesn't work.

I'm pasting the contents of the file (unmodified) which I've tried to
follow from the Getting Started document. I was trying to get the
custom domain approach working, but I never seem to get the lazy
function to be called.

The expected result from the code below would be to have multiple
lines of output that says "Getting the friends of user # ;)" but I
don't see those. There are no compilation errors, and I don't see
anything obviously wrong from the implementation and how I understand
Lazy functions. I'm just not sure about how lazy functions though can
be made part of a domain though -- didn't find anything in the Getting
Started guide about it.

Help would be very much appreciated (BTW I'm using Proto that's in
Boost 1.38.0, building with GCC 4.0 in Mac OSX 10.5.6):

---->8--

#include <iostream>
#include <boost/proto/proto.hpp>
#include <vector>

namespace mpl = boost::mpl;
namespace fusion = boost::fusion;
namespace proto = boost::proto;

using proto::_;

using std::vector;
using std::cout;
using std::endl;

struct user_tag;

template <class Tag>
struct placeholder {};

struct friendster_action_context
: proto::callable_context<friendster_action_context const>
{
    uint32_t user_id;

    friendster_action_context(uint32_t id) : user_id(id) {}

    friendster_action_context(friendster_action_context const & other)
: user_id(other.user_id) {}

    friendster_action_context & operator= (friendster_action_context other) {
        other.swap(*this);
        return *this;
    }

    void swap(friendster_action_context & other) {
        std::swap(user_id, other.user_id);
    }

    typedef uint32_t result_type;

    result_type operator() (proto::tag::terminal, placeholder<user_tag>) const {
        return this->user_id;
    }
};

template <class Expr>
struct friendster_action;

struct friendster_action_domain :
proto::domain<proto::pod_generator<friendster_action> >
{};

template <class Expr>
struct friendster_action {
    BOOST_PROTO_EXTENDS(Expr, friendster_action<Expr>,
friendster_action_domain);

    typedef void result_type;

    result_type operator()(uint32_t id) const {
        friendster_action_context ctx;
        ctx.user_id = id;
        return proto::eval(*this, ctx);
    }
};

friendster_action<proto::terminal<placeholder<user_tag> >::type> const
user = {{}};

struct friend_fun {
    typedef vector<uint32_t> result_type;
    template <class T>
    result_type operator() (T id) const {
        cout << "Getting the friends of user " << id << " ;)" << std::endl;
        return result_type();
    };
};

template <class Arg>
typename proto::result_of::make_expr<
proto::tag::function,
friend_fun,
typename proto::result_of::as_child<Arg const>::type
>::type
friends(Arg const & arg) {
    return proto::make_expr<proto::tag::function>(
                                                  friend_fun(),
                                                  proto::as_child(arg)
                                                  );
}

#include <algorithm>

using namespace std;

int main(int argc, char * argv[]) {
    uint32_t users[] = { 1, 2, 3, 4 };
    uint32_t * begin = users;
    uint32_t * end = users + 4;
    cout << "Here they are: " << endl;
    for_each(begin, end, friends(user));
    string input;
    cin >> input;
    return 0;
}

---->8--

-- 
Dean Michael Berris | Software Engineer, Friendster, Inc.
blog.cplusplus-soup.com | twitter.com/mikhailberis |
linkedin.com/in/mikhailberis | profiles.friendster.com/mikhailberis |
deanberris.com

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