Boost logo

Boost :

Subject: Re: [boost] [boost.process] 0.6 Redesign
From: Klemens Morgenstern (klemens.morgenstern_at_[hidden])
Date: 2016-04-19 19:15:31

> `execute` is a function that takes `T&&...`, but certain types are
> going to fail internally. For example, the `execute` signature allows
> for zero arguments which does not make sense. And what advantage is
> there to making the first argument templated instead of a `const
> char*`? Is there an operating system that takes an argument other than
> a null-terminated c-style string for the command parameter? It is easy
> to provide forwarding overloads for other types such as
> boost::filesystem.

Good point, especially since the failure when passing zero arguments
will only come up at run-time. That's indeed bad, but could easily be
solved with an enable_if or static_assert.
It is actually not a requirement to put the command first in the execute
function, which is why that is not overloaded but just a part of the
T&&...; this is basically inherited from 0.5 and I see no reason, why
the command should be first.

> And it would be nice if the command-line arguments
> to the process were not intermingled with the options. What if instead
> of `execute` you had a function `command` that returned a callable with
> overloads for `operator|`, `operator<`, and `operator>`:
> (command("echo", "-n", "some text") > "foo.txt")(options...)
> (command("wget", url) | command("sha256sum") > ostream))()

I really like this idea, and thought about features like that, but you
always have the downside to it, that it's to limited. But: maybe this
can be added, since execute is a template, you could build this with the
execute function.

The actual Problem I'd have here is, that I don't get a child-handle for
each call back, which bothers me. Because this child binds the process
by default, which means it waits for the exit on destructor call. This
can be changed by calling detach, but it's hard to see how that would be
managed in a configurable way in your example.

I think that should be considered a library one implements with, i.e.
atop boost.process. So basically this constructs a functor:

std::future<std::string> fut;
auto exec = command("wget", url) | command("sha256sum") > fut ;
//and now we invoke the boost.process impl:

Seperating that (though not necessarily in two libraries) has a lot of
advantages: boost.process can implement all the low-level stuff in a
portable way, and the other library (let's call it boost.neat_process)
can than run completely wild with expression-templates without needing
to be concerned about the syscalls etc..

> I would consider converting static functions into constexpr functors if
> they are templated - or at least the `execute` function. This would make
> the functions in the library easier to use with std::bind and
> boost::fit which might be useful.

Makes sense, I use this pattern for the initializers already anyway.

Boost list run by bdawes at, gregod at, cpdaniel at, john at