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