#include <utility>
#define EXEC_MEMBER_PROC_IF_PRESENT(ProcName) namespace ProcName {\
void ExecIfPresent(...) throw() {}\
\
template <class C, typename... TArgs>\
void ExecIfPresent(C& obj, TArgs&... args) {\
obj.ProcName(std::forward<TArgs>(args)...);\
}\
};
// If NOT exists - returns the 'DefaultValue'
// 'DefaultValue' SHOULD be the same type as a decltype(*.FuncName())
// Works with static/const/virtual funcs
#define EXEC_MEMBER_FUNC_IF_PRESENT(FuncName, DefaultValue) namespace FuncName {\
template <typename TReturnType = decltype(DefaultValue)>\
auto ExecIfPresent(...) -> TReturnType {\
return std::move(DefaultValue);\
}\
\
template <class C, typename... TArgs>\
auto ExecIfPresent(C& obj, TArgs&... args)\
-> decltype(obj.FuncName(std::forward<TArgs>(args)...))\
{/* do NOT use 'const C& obj' NOR 'C::FuncName()!'*/\
return std::move(obj.FuncName(std::forward<TArgs>(args)...));\
}\
};
EXEC_MEMBER_FUNC_IF_PRESENT(getHashIfKnown, 0U);
#include<cassert>
#include<cstring>
#include<string>
#include<iostream>
int main() {
std::string str = "test str";
auto hash = getHashIfKnown::ExecIfPresent(str);
assert(!hash);
std::cout << "str: " << hash << std::endl;
struct MyStr {
MyStr(const char* str) throw() {
if(str) {
strcpy(buf, str);
len = strlen(buf);
}
}
size_t getHashIfKnown() const throw() {
size_t hash = 0U;
for(size_t idx = 0U; idx < len; ++idx) {
hash += buf[idx] * (idx + 1U);
}
return hash;
}
size_t len = 0U;
char buf[256U];
} myStr = "we don't need no water!";
hash = getHashIfKnown::ExecIfPresent(myStr);
assert(hash);
std::cout << "myStr: " << hash << std::endl;
}