1

I am currently trying to get the following very simple boost::phoenix::lambda to compile:

#include <iostream>

#include <boost/phoenix/scope.hpp>

int main() {
    boost::phoenix::lambda[std::cout << "Lambda!!"]();
}

However, this generates a host of errors (too much to post here), none which make any sense to me. Here is an excerpt of the compiler output:

error: 'std::ios_base::ios_base(const std::ios_base&)' is private 
       within this context
error: initializer for 
       'boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, 
        boost::proto::argsns_::term<boost::phoenix::vector0<> >, 0l>::proto_child0 
        {aka boost::phoenix::vector0<>}' must be brace-enclosed

I am compiling these using MinGW 4.7.2 on Windows XP with Boost 1.53.0. What am I doing wrong?

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • I am not familiar with Boost::Phoenix but in c++11, you'd write: `[] () { std::cout << "Lambda!!"; }` – jt234 May 13 '13 at 10:31
  • 2
    The expression inside the square brackets is evaluated, and then the lambda tries to copy the returned `std::ostream` object, which it can't, because iostreams are non-copyable. Did you think that wrapping an expression in `phoenix::lambda[...]` would magically make it lazy? – Xeo May 13 '13 at 10:33
  • @Xeo that should be an answer not a comment – Salgar May 13 '13 at 10:37
  • 3
    Try `boost::phoenix::lambda[boost::phoenix::ref(std::cout) << "Lambda!!"]()();` for which you you need `boost/phoenix/phoenix.hpp`. If the double `()()` surprises you then do not start using `boost::phoenix::lambda` before knowing the basics, of which `lambda` is not. – Luc Danton May 13 '13 at 10:44
  • 1
    @LucDanton: Make it an answer. – wilx May 13 '13 at 11:00
  • @Xeo: I guess I was mislead by the fact that the [documentation for `boost::phoenix::let`](http://www.boost.org/doc/libs/1_53_0/libs/phoenix/doc/html/phoenix/modules/scope/let.html) uses a very similar example. I had a problem and though `lets use lambda`, and then I had two problems... – Björn Pollex May 13 '13 at 11:50
  • @BjörnPollex: `let` uses special placeholders that kick off expression-template generation and all that stuff. – Xeo May 13 '13 at 11:52

1 Answers1

4

Firstly, always

#include <boost/phoenix/phoenix.hpp>

unless you know what you're doing.

Secondly, you need to make either operand of operator<< be a phoenix terminal, otherwise, it will be just

std::cout << "Lambda!!"

which is an expression of type std::ostream&...

Now, you could do anything, really, e.g.

phx::ref(std::cout) << "Lambda!!"

or

std::cout << phx::val("Lambda!!")

Either will compile.

sehe
  • 374,641
  • 47
  • 450
  • 633