This definitely steps into both "language variant" and Pattern Matching territory. 
I am not sure what optimization we can expect from "language variant", but PM should give us close to your ideal code

void main(int argc, char const* const* argv){
    inspect(halve(args))
      Numeric x => std::cout << "You passed 2*(" << x << ") arguments\n";
    return 0;
}



On Tue, Feb 4, 2020 at 1:27 PM Jake Arkinstall via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi all,

I want to put this out there and see if there is any interest or not for a far future C++ version. It's along the lines of something I use for data pipelines with components that return one of many possible types (or yield multiple of them).

I want the compiler to be able to effectively optimise several return types at compile time, without resorting to the Variant's use of double-branching at runtime (branch on a condition, create some T, wrap it in a variant, store it in X, unwrap X, branch on T). I also want it to feel more natural to use, almost as effortless as python, but with the power of C++'s type engine.

The use of callbacks allows the compiler to reason about different branches rather effectively - in both clang and gcc, with full optimisation enabled, this produces far smaller binaries, faster runtimes and (on the vanity side) much nicer assembly.

Here's the idea:

Through templates, a single template function can generate many functions, each determined by the signatures of one or more calls that exist in the code being compiled. It is possible to use this mechanism to flip that idea on its head, allow multiple return types T, and generate functions at the call site to handle each T.

Consider a placeholder type, which I'll call var, that acts as "one of many types, to be determined at compile time". This keyword can be applied as a return type to a function:

var halve(unsigned i){
    if(i % 2 == 0){
        return i / 2; // unsigned path
    }else{
        return i * 0.5; // double path
    }
}

And it can be used as a holder for that return type:

void main(int argc, char const* const* argv){
    var x = halve(args);
    std::cout << "You passed 2*(" << x << ") arguments\n";
    return 0;
}

This can be achieved by injecting callbacks which have x defined as the type being passed during invocation. In this case, the var function could be rewritten, implicitly, as:

template<typename callback_t>
void halve(callback_t&& callback, unsigned i){
    if(i % 2 == 0){
        std::invoke(callback, i / 2);
        return;
    }else{
        std::invoke(callback, i * 0.5);
        return;
    }
}

And the function with the var placeholder could be rewritten as:

struct main_x_handler{
    void operator()(unsigned x){
        std::cout << "You passed 2*(" << x << ") arguments\n";
        return 0;
    }
    void operator()(double x){
        std::cout << "You passed 2*(" << x << ") arguments\n";
        return 0;
    }
};
void main(int argc, char const* const* argv){
    return halve(main_x_handler{}, argc);
}

such that all code that follows the first read of x is diverted into a callback that caters for each possible type that x can adopt.

Furthermore, we can add a "multivar" keyword that allows yielding, rather than returning after the first invocation of the callback. Placed in a loop, this invokes the remainder of the calling function's body for each such yield.

multivar get_halves(unsigned start, unsigned end){
    for(unsigned i = start; i < end; ++i){
         yield halve(i);
    }
void foo(unsigned start, unsigned end){
    for(var x : get_halves(start, end)){
        // use x
    } 
}

This is particularly useful for me, at least, because I use cleaning methods that may hold back events until further information is received, at which point it flushes many events in sequence.

This proposal will likely also include a mechanism for switching on types. I'm also thinking of using template/concept syntax in place of var.

The idea is just a rough sketch at the moment, and I don't want to take it too far without some feedback.

Thanks, 
Jake
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals