I would like to use instances of a non-proto class as proto terminals for all purposes. To enable this functionality, I use is_terminal metafunction that I pass to BOOST_PROTO_DEFINE_OPERATORS(). This actually defines the operators, so the following expression makes an expression tree, as expected: non_proto_obj * proto_obj; However, I cannot do this: non_proto_obj = proto_obj; Or this: non_proto_obj[proto_obj]; While the opposite does compile: proto_obj = non_proto_obj; proto_obj[non_proto_obj]; How to solve this issue? Thanks! P.S.: here is an sscce: /////////////////// #include <iostream> #include <boost/proto/proto.hpp> #include <boost/mpl/int.hpp> namespace mpl = boost::mpl; namespace proto = boost::proto; using proto::_; template<typename Expr> struct my_expression; struct my_domain : proto::domain<proto::generator<my_expression> > {}; template<int I> struct placeholder {}; template<typename Expr> struct my_expression : proto::extends<Expr, my_expression<Expr>, my_domain> { explicit my_expression(Expr const &expr = Expr()) : my_expression::proto_extends(expr) {} BOOST_PROTO_EXTENDS_USING_ASSIGN(my_expression<Expr>) }; const my_expression<proto::terminal<placeholder<1>>::type> _1; namespace app { struct non_proto_type {}; template <typename T> struct is_terminal : mpl::false_ {}; template<> struct is_terminal<non_proto_type> : mpl::true_ {}; BOOST_PROTO_DEFINE_OPERATORS(is_terminal, my_domain) non_proto_type non_proto; } int main() { _1 = app::non_proto; // ok, builds temporary proto expression //app::non_proto = _1; // does not compile! no operator= _1[app::non_proto]; // ok //app::non_proto[_1]; // does not compile! no operator[] (+app::non_proto)[_1]; // ok! applying unary + to make a proto expression first, then operator[] is available }