• Re: How to make the Process ctor work for different R =?UTF-8?Q?type=3F

    From Sam@21:1/5 to wij on Tue Nov 19 07:07:48 2024
    wij writes:

    struct Process {
    template<typename R>
    explicit Process(R (*pfunc)(), bool ret_int=false) {
    int pid= fork();
    if(pid==-1) {
    throw "Error";
    }
    if(pid==0) {
    if(ret_int) {
    _exit( pfunc() ); // error: invalid use of void expression
    } else {
    pfunc(); // ret value ignored
    _exit(0);
    }
    }
    };
    }

    The issue is _exit(int) require int type.

    void f();
    Process proc(f); // error: R is void

    So, how to make the Process ctor work for different R type?

    For starters this has to be resolved at compile time, not run time.
    Therefore you can't use ret_int, whose purpose is very obvious, because you don't know its value until runtime. Just because it has a default value
    doesn't turn it into a compile-time, constexpr value.

    Fortunately there is a very convenient R here. So the first step is to get
    rid of the useless `ret_int`.

    template<typename R>
    explicit Process(R (*pfunc)()) {

    And now this becomes a boring case of constexpr if:

    #include <type_traits>

    // …


    if constexpr(!std::is_same_v<R,void>)
    _exit( pfunc() );
    } else {
    pfunc();
    _exit(0);
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Sam@21:1/5 to wij on Wed Nov 20 07:51:26 2024
    wij writes:


        if constexpr(!std::is_same_v<R,void>)
          _exit( pfunc() );
        } else {
             pfunc();
             _exit(0);
        }

    Thanks. I need C++11 way.

    The C++11 way would involve using specialization, and some major
    refactoring, to avoid code duplication.

    explicit Process::Process<void>(void (*pfunc)()) {

    followed by a specialization declaration:

    template<> explicit Process::Process<void>(void (*pfunc)()) {

    And, as I mentioned, the common code would need to be factored out, in some way, to avoid duplication.

    Updating the compiler to something less than a decade old will probably be
    much easier.

    I thought about using a delegating constructor, something like:

    template<> explicit Process::Process<void>(void (*pfunc)())
    : Process([&]{ pfunc(); return 0; })
    {
    }

    but this wouldn't work for the obvious reason. One could try to get this to work with a std::function, although I think this would be somewhat tricky
    for overload resolution to work correctly.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)