#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;
}