jeudi 14 juillet 2022

Simple template to pass a c++ member method as a callback

I have a set of classes which have many very similar methods, grouped into 2 call signatures. These calls are of the form:

bool fn( const std::string& ) and bool fn( const std::vector<std::string>& )

I need to do some common logic around each call and I'm trying to make my life easy but without much luck. Conceptually, the wrapper logic signature looks like the following:

bool wrap( config::method, key, values, flag )

I have code that compiles but it is more complicated than I want. This is the actual signature (there will be two wrappers, one for each signature type):

template <typename T, bool(T::*fn)(const std::string&)>
bool CFG_STR( T& cfg, const char* key, Nodes data, bool flag ) { /* ... cfg.*fn(x) ... */ }

and this is the caller:

configClassWithVeryLongName config;
success &= CFG_STR<
    configClassWithVeryLongName,
    &configClassWithVeryLongName::methodCall
>( config, "key", dataStore, configFlag );

Is there a more compact and less fragile way to write this? I can reduce it to this:

#define MAC_STR(c,m,k,d,f) CFG_STR<typeof( c ), m>( c, k, d, f )

configClassWithVeryLongName config;
success &= MAC_STR( config, &configClassWithVeryLongName::methodCall, "key", dataStore, configFlag );

I would really like to remove the class name prefix and simply pass methodCall or "methodCall", and not use CPP macros. Is there a clever way to do this cleanly? I've tried a few things like combining typeof with the # paste macro to form the method name but without any success. Modifying the 'config...' classes is not an option because they do not all inherit from a common base class.

Thanks.

Aucun commentaire:

Enregistrer un commentaire