|
Boost Users : |
Subject: Re: [Boost-users] [Proto] First steps
From: Eric Niebler (eric_at_[hidden])
Date: 2010-11-09 15:30:56
On 11/9/2010 11:27 AM, Eric Niebler wrote:
>> Any idea?
>
> As you have learned, Proto is not move-aware. My hand-wavy solution
> would be to (a) be sure that everything is held by value in an ET. With
> 1.42, that's by using proto::by_value_generator. In 1.44, the preferred
> solution is with a domain-specific as_child implementation. And (b) to
> wrap move-only types in a "copyable" type that, in its copy ctor, moves
> the wrapped value.
>
> I'll see if I can come up with an example that demonstrates.
Here is a Proto algorithm that deep-copies a tree that contains a
move-only object. This doesn't directly answer your question, but might
get you moving in the right direction. (Tested on VC10.)
#include <boost/proto/proto.hpp>
#include <typeinfo>
#include <string>
#include <iostream>
namespace proto=boost::proto;
namespace mpl=boost::mpl;
using proto::_;
// A move-only type
struct move_only
{
move_only() : what_("valid") {}
move_only(move_only && that) : what_("valid") { that.what_ =
"moved from"; }
~move_only() { what_ = "deleted"; }
char const *what_;
private:
move_only(move_only const &);
move_only& operator=(move_only const &);
};
// A wrapper for move-only types that moves on copy
template<typename T>
struct move_on_copy
{
explicit move_on_copy(T && t)
: t_(std::move(t))
{}
move_on_copy(move_on_copy const & that)
: t_(std::move(that.t_))
{}
private:
move_on_copy &operator=(move_on_copy const &);
mutable T t_;
};
// A callable that wraps a move-only type in move_on_copy
struct _move : proto::callable
{
template<typename Sig>
struct result;
template<typename This, typename T>
struct result<This(T)>
{
typedef move_on_copy<typename
boost::remove_reference<T>::type> type;
};
template<typename T>
move_on_copy<typename boost::remove_reference<T>::type>
operator()(T && t) const
{
return move_on_copy<typename
boost::remove_reference<T>::type>(std::move(t));
}
};
// A type-trait we can use to detect move-only types
template<typename T>
struct is_move_only
: mpl::false_
{};
template<typename T>
struct is_move_only<T &>
: is_move_only<T>
{};
template<typename T>
struct is_move_only<T const>
: is_move_only<T>
{};
template<>
struct is_move_only<move_only>
: mpl::true_
{};
// A pattern that matches move-only terminals
struct MoveOnlyTerminal
: proto::and_<
proto::terminal<_>
, proto::if_<is_move_only<proto::_value>()>
>
{};
// An algorithm that deep-copies a Proto expression tree, wrapping
// move-only types in move_on_copy
struct DeepCopy
: proto::or_<
proto::when<MoveOnlyTerminal,
proto::_make_terminal(_move(proto::_value))>
, proto::when<proto::terminal<proto::_>,
proto::_make_terminal(proto::_byval(proto::_value))>
, proto::nary_expr<proto::_, proto::vararg<DeepCopy> >
>
{};
int main()
{
move_only a;
move_only b(std::move(a));
move_on_copy<move_only> e(std::move(b));
move_on_copy<move_only> f(e); // move!
proto::terminal<move_only>::type y = {std::move(b)};
// This deep-copies the tree, wrapping all move-only types
// in move_on_copy.
DeepCopy()(1 + y + 42);
}
HTH,
-- Eric Niebler BoostPro Computing http://www.boostpro.com
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