1

Following the Expressions as Fusion Sequences section of the Proto User Guide, I get to the point where I iterate over a flattened proto expression: _1 + 2 + 3 + 4:

#include <iostream>
#include <boost/phoenix.hpp>

namespace proto   = boost::proto;
namespace fusion  = boost::fusion;
namespace phoenix = boost::phoenix;

struct display
{
  template<typename T>
  void operator()(T const &t) const
  {
    std::cout << t << std::endl;
  }
};

boost::proto::terminal<int>::type const _1 = {1};

int main(int argc, char *argv[])
{
  fusion::for_each(
    fusion::transform(
      proto::flatten(_1 + 2 + 3 + 4)
    , proto::functional::value()
    )
  , display()
  );
  return 0;
}

The _1 placeholder is defined as shown above using proto::terminal. I'd also like to use Boost Phoenix; however, if I instead use the version of _1 defined in boost::phoenix::arg_names in the call to fusion::for_each, I get an error: cannot bind ‘std::ostream {aka std::basic_ostream}’ lvalue to ‘std::basic_ostream&&’. Can I use Phoenix placeholders like this with a Fusion transform?

user2023370
  • 10,488
  • 6
  • 50
  • 83

1 Answers1

3

There is no ostream inserter for phoenix::arg_names::_1. We can easily add one, though. This compiles for me with clang++ (trunk):

#include <iostream>
#include <boost/phoenix.hpp>

namespace proto   = boost::proto;
namespace fusion  = boost::fusion;
namespace phoenix = boost::phoenix;

struct display
{
  template<typename T>
  void operator()(T const &t) const
  {
    std::cout << t << std::endl;
  }
};

namespace boost { namespace phoenix
{
  template<int N>
  std::ostream& operator<<(std::ostream& sout, argument<N> const& arg)
  {
    return sout << "_" << N;
  }
}}

int main()
{
  fusion::for_each(
    fusion::transform(
      proto::flatten(phoenix::arg_names::_1 + 2 + 3 + 4)
    , proto::functional::value()
    )
  , display()
  );
}
Eric Niebler
  • 5,927
  • 2
  • 29
  • 43
  • Do you by any chance know why I get an error with `proto::display_expr(fusion::at_c<0>(proto::flatten(_1+2+3+4)));`? – user2023370 Mar 05 '13 at 12:20
  • 2
    @user2023370 `fusion::at_c` requires a [`Random Access Sequence`](http://www.boost.org/libs/fusion/doc/html/fusion/sequence/concepts/random_access_sequence.html) and the result of `proto::flatten` is just a [`Forward Sequence`](http://www.boost.org/libs/fusion/doc/html/fusion/sequence/concepts/forward_sequence.html). You can use `proto::display_expr(fusion::at_c<0>(fusion::as_vector(proto::flatten(_1+2+3+4))));`. –  Mar 05 '13 at 14:55