Created
May 25, 2022 07:40
-
-
Save brunoalr/7fcf786a7342b21ff22b2fa93d1d90db to your computer and use it in GitHub Desktop.
fun with pointers to member functions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://godbolt.org/z/3s1r3K4rs | |
#include <string> | |
// For c++ versions earlier than 17 | |
#if __cplusplus < 201703L | |
// See https://isocpp.org/wiki/faq/pointers-to-members#macro-for-ptr-to-memfn | |
// and https://isocpp.org/wiki/faq/big-picture#use-evil-things-sometimes | |
#define CALL_MEMBER_FN(object,ptrToMember) (((object).*(ptrToMember))()) | |
#else | |
#include <functional> | |
#define CALL_MEMBER_FN(object, ptrToMember) (std::invoke(ptrToMember, object)) | |
#endif | |
struct ThingHolder { | |
std::string thing1; | |
std::string thing2; | |
std::string thingN; | |
}; | |
class Builder { | |
public: | |
Builder& setThing1(std::string aThing1) | |
{ | |
mThing.thing1 = std::move(aThing1); | |
return *this; | |
} | |
Builder& setThing2(std::string aThing2) | |
{ | |
mThing.thing2 = std::move(aThing2); | |
return *this; | |
} | |
Builder& setThingN(std::string aThingN) | |
{ | |
mThing.thingN = std::move(aThingN); | |
return *this; | |
} | |
const ThingHolder build() const | |
{ | |
return mThing; | |
} | |
private: | |
ThingHolder mThing; | |
}; | |
struct Getter { | |
std::string thing1; | |
std::string thing2; | |
std::string thingN; | |
const std::string& GetThing1() const | |
{ | |
return thing1; | |
} | |
const std::string& GetThing2() const | |
{ | |
return thing2; | |
} | |
const std::string& GetThingN() const | |
{ | |
return thingN; | |
} | |
}; | |
int main() { | |
using GetterMemFn = const std::string& (Getter::*)(void) const; | |
Getter objA; | |
objA.thing1 = "1"; | |
Getter objB; | |
objB.thing2 = "123"; | |
const auto magicFunction = [&objA, &objB](const GetterMemFn& memFn) { | |
return !CALL_MEMBER_FN(objA, memFn).empty() ? | |
CALL_MEMBER_FN(objA, memFn) : | |
CALL_MEMBER_FN(objB, memFn); | |
}; | |
const auto thingHolder { | |
[&]{ | |
return Builder{} | |
.setThing1(magicFunction(&Getter::GetThing1)) | |
.setThing2(magicFunction(&Getter::GetThing2)) | |
.setThingN(magicFunction(&Getter::GetThingN)) | |
.build(); | |
}() | |
}; | |
return thingHolder.thing1.size(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment