On Mon, May 25, 2020 at 9:54 AM Nikolay Mihaylov via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
You are correct, this was my first implementation. I think "constexpr if" is not very readable and I usually prefer tag dispatch.

About the arguments - yes, those are different types, but [...]

The problem is: Because `&A::f` and `&B::f` are both of type `int(*)(int)`, it is physically impossible to write any function that accepts `&A::f` and rejects `&B::f`.

struct A { static int f(int); };
struct B { static int f(int); };
int g(int);
int main() {
    A a;
    class_invoke(&A::f, a, 1);  // If this is OK...
    class_invoke(&B::f, b, 1);  // ...then this must also be OK...
    class_invoke(g, b, 1);  // ...and so must this.
}

It would be interesting to explore how the Ranges library (new in C++20) deals with this "problem." My guess is that they deal with it the same way as std::invoke does; that is, they don't care about static methods.

 
suppose the class is passed from somewhere, here is my real code:

template<class PROTOCOL, class DB_ADAPTER, class CONNECTION>
class KeyValueWorkerProcessor{
// ... 
    template<typename F>
    WorkerStatus do_accumulate_(F func){
        const auto &p = protocol_.getParams();
        if (p.size() != 4)
            return err_BadRequest_();
        const auto &key    = p[1];
        uint16_t const count = from_string<uint16_t>(p[2]);
        const auto &prefix = p[3];
        protocol_.response_strings(buffer_, class_invoke(db_, func, key, count, prefix) );

Looks good to me. Garrett provided you with a nice short 8-line implementation of `class_invoke`.

Current implementation works and looks very nice and clear, isn't it?

Yep. Add Garrett's 8-liner to your codebase and ship it!

–Arthur