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
#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
struct result
{
typedef move_on_copy type;
};
template<typename T>
move_on_copy
operator()(T && t) const
{
return move_on_copy(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
: is_move_only<T>
{};
template<typename T>
struct is_move_only<T const>
: is_move_only<T>
{};
template<>
struct is_move_only
: mpl::true_
{};
// A pattern that matches move-only terminals
struct MoveOnlyTerminal
: proto::and_<
proto::terminal<_>
, proto::if_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
, proto::whenproto::_,
proto::_make_terminal(proto::_byval(proto::_value))>
, proto::nary_expr
>
{};
int main()
{
move_only a;
move_only b(std::move(a));
move_on_copy e(std::move(b));
move_on_copy f(e); // move!
proto::terminal::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