Boost logo

Boost :

Subject: Re: [boost] [boost.process] 0.6 Redesign
From: Lee Clagett (forum_at_[hidden])
Date: 2016-04-19 18:23:40

On Tue, 19 Apr 2016 20:51:52 +0200
Klemens Morgenstern <klemens.morgenstern_at_[hidden]> wrote:
> Am 19.04.2016 um 20:08 schrieb Niall Douglas:
> > On 19 Apr 2016 at 13:34, Klemens Morgenstern wrote:
> >
> [...]
> >
> > A freeform constructor with tagged parameters is absolutely right
> > for when the parameters can be extended by third party code. Here
> > though parameter types are completely known, so the appropriate
> > design for when there are too many parameters and/or you'd like to
> > name them is to pass a tagged tuple aka a struct.
> >
> > The choice to use metaprogramming should always confer an absolute
> > design win over all other design alternatives given the increased
> > compile times, memory usage, brittleness and other factors.
> > Metaprogramming is very much not free of cost. It should be used as
> > sparingly as possible in publicly facing library APIs.
> >
> > In particular I find Process' use of a freeform constructor
> > gratuitous given the much simpler close substitutes like passing a
> > struct.
> >
> Well, it doesn't seem like we'll agree any time soon, but that's imho
> the beauty of open-source. If you have any design for a process
> library, I would be very much interested in it.
> Btw: boost.process 0.5 only allowed initializers to be passed to the
> execute function, i.e. you had to write
> execute(set_exe("gcc"), set_args({"--version"});
> I intentionally changed that, so one could write
> execute("gcc", "--version");
> because I find this much more intuitive (i.e. design win). This
> allows more parameter to be passed, like std::error_code or
> boost::asio::io_service. And unlike your proposed "make everything
> async" solution, you only pay for it, if you use it. I could add an
> exe_args initializer, so you can get rid of the initializer building
> altogether.

`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. 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))()

Which I _think_ has the desired precedence (relational before `|`). In
fact, why not include `||` and `&&` - is this too crazy? The immediate
invocation of each operand is irrelevant to this use case. Also, the
returned object could _always_ be a nullary-callable, but with named
parameters for modifying options.

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.


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