- #include <iostream> 
- #include <type_traits> 
- #include <functional> 
- #include <cstdint> 
- #include <typeinfo> 
- #include <string> 
-   
- // Just gonna do this for the sake of our example here. 
- using FilePath = std::string; 
-   
- // Parameter match checking. 
- namespace ParameterCheck { 
-     template<typename T, typename... Ts> struct parameter_match : public std::false_type {}; 
-   
-     // Declare (GetColor, int16_t*) valid. 
-     template<> struct parameter_match<int (*)(int16_t*), int16_t*> : public std::true_type {}; 
-   
-     // Declare (GetFile, FilePath&) valid. 
-     // template<> struct parameter_match<int (*)(FilePath&), FilePath&> : public std::true_type {}; // You'd think this would work, but... 
-     template<> struct parameter_match<int (*)(FilePath&), FilePath> : public std::true_type {}; // Nope! 
-     // For some reason, reference-ness isn't part of the templated type.  It acts as if it was "template<typename T> void func(T& arg)" instead. 
-   
-     // Declare (WriteDocument, const FilePath&, const char*, bool) valid. 
-     // template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath, const char*, bool> : public std::true_type {}; 
-     // template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), const FilePath&, const char*, bool> : public std::true_type {}; 
-     template<> struct parameter_match<int (*)(const FilePath&, const char*, bool), FilePath, const char*, bool> : public std::true_type {}; 
-     // More reference-as-template-parameter wonkiness: Out of these three, only the last works. 
-   
-     // Declare everything without a parameter list valid. 
-     template<typename T> struct parameter_match<T (*)()> : public std::true_type { }; 
- } // namespace ParameterCheck 
-   
- // Discount return type deduction: 
- namespace ReturnTypeCapture { 
-     // Credit goes to Angew ( http://stackoverflow.com/a/18695701/5386374 ) 
-     template<typename T> struct ret_type; 
-   
-     template<typename RT, typename... Ts> struct ret_type<RT (*)(Ts...)> { 
-         using type = RT; 
-     }; 
- } // namespace ReturnTypeCapture 
-   
- // Alias declarations: 
- template<typename F, typename... Ts> using PChecker = ParameterCheck::parameter_match<F, Ts...>; 
- template <typename F> using RChecker = typename ReturnTypeCapture::ret_type<F>::type; 
-   
-   
- // --------------- 
-   
- // Quick implementations of your example functions. 
-   
- int GetColor(int16_t* color) { 
-     std::cout << "GetColor(int16_t*) with parameter: " << *color << std::endl; 
-     return 3; 
- } 
-   
- int GetFile(FilePath& file) { 
-     std::cout << "GetFile(FilePath&)." << std::endl; 
-     std::cout << "..." << file << "?  Get it yourself!" << std::endl; 
-     return -6; 
- } 
-   
- int WriteDocument(const FilePath& file, const char* fileFormatName, bool askForParams) { 
-     std::cout << "WriteDocument(const FilePath&, const char*, bool) with: " 
-               << file << ", " << fileFormatName << ", and " << std::boolalpha 
-               << askForParams << "." << std::noboolalpha << std::endl; 
-     std::cout << "Eh, I'll write it tomorrow." << std::endl; 
-     return 8; 
- } 
-   
- // --------------- 
-   
- // The actual calling function, C++11 style. 
- template<typename Func, typename... Ts> auto caller2(std::true_type x, Func f, Ts... args) -> RChecker<Func> { 
-     std::cout << "Now calling... "; 
-     return f(args...); 
- } 
-   
- // Parameter mismatch overload. 
- template<typename Func, typename... Ts> auto caller2(std::false_type x, Func f, Ts... args) -> RChecker<Func> { 
-     std::cout << "Parameter list mismatch." << std::endl; 
-     return static_cast<RChecker<Func> >(0); // Just to make sure we don't break stuff. 
- } 
-   
- // Wrapper to check for parameter mismatch, C++14 style. 
- template<typename Func, typename... Ts> auto caller(Func f, Ts... args) /* -> RChecker<Func> */ { 
-     // return caller2(ParameterCheck::parameter_match<Func, Ts...>{}, f, args...); 
-     return caller2(PChecker<Func, Ts...>{}, f, args...); 
- } 
-   
- // --------------- 
-   
- // To show what std::true_type and std::false_type act as. 
-   
- template<bool N> void fnarg2(std::integral_constant<bool, N> x) { 
-     std::cout << "Integral constant<bool, N> value: " << x.value << std::endl; 
- } 
-   
- template<typename F, typename... Ts> void fnarg(F f, Ts... ts) { 
-     fnarg2(ParameterCheck::parameter_match<F, Ts...>{}); 
- } 
-   
- // --------------- 
-   
- // Something I used to get things working, I left it here to show something odd: 
-   
- // Which one is true and which is false flips depending on whether the parameter is T or T&. 
- template<typename T> void sameness(T& t) { 
-     std::cout << std::boolalpha; 
-     std::cout << "cfp is const: " << std::is_same<T, const FilePath>::value << std::endl; 
-     std::cout << "cfp ain't const: " << std::is_same<T, FilePath>::value << std::endl; 
-     std::cout << std::noboolalpha; 
- } 
-   
- // --------------- 
-   
- // Return type sorcery: 
-   
- std::string f1() { return std::string("Nyahaha."); } 
-   
- int f2() { return -42; } 
-   
- char f3() { return '&'; } 
-   
- // template<typename R, typename F> auto rtCaller2(R r, F f) -> typename R::type { 
- // template<typename F> auto rtCaller2(F f) -> typename ReturnTypeCapture::ret_type<F>::type { 
- template<typename F> auto rtCaller2(F f) -> RChecker<F> { 
-     return f(); 
- } 
-   
- template<typename F> void rtCaller(F f) { 
-     // auto a = rtCaller2(ReturnTypeCapture::ret_type<F>{}, f); 
-     auto a = rtCaller2(f); 
-     std::cout << a << " (type: " << typeid(a).name() << ")" << std::endl; 
- } 
-   
- // --------------- 
-   
- int main()  { 
-     int16_t i = 3333; 
-     FilePath fp = "C:\\Windows\\win.ini"; 
-     const FilePath cfp = (const FilePath) fp; // In case you didn't know, it's a const FilePath. ^_^ 
-     const char* cc = "Fred Format\n"; 
-     bool b = true; 
-   
-     // Checking int(*)(int16_t*): 
-     auto gc = caller(GetColor, &i);                                   // Valid call. 
-     caller(GetColor, &i, i);                                // Invalid call. 
-     std::cout << std::endl; 
-   
-     // Checking int(*)(FilePath&): 
-     auto gf = caller(GetFile, fp);                                    // Valid call. 
-     caller(GetFile, main);                                  // Invalid call. 
-     std::cout << std::endl; 
-   
-     //Checking int(*)(const FilePath&, const char*, bool): 
-     auto wd = caller(WriteDocument, cfp, cc, b);                      // Valid call. 
-     caller(WriteDocument, cfp, const_cast<char*>(cc), b);   // Invalid call. 
-     std::cout << std::endl; 
-   
-     auto f_1 = caller(f1); 
-     auto f_2 = caller(f2); 
-     auto f_3 = caller(f3); 
-     std::cout << std::endl; 
-   
-     std::cout << "Return values: " << gc << ", " << gf << ", " << wd << ", " 
-               << f_1 << ", " << f_2 << ", and " << f_3 <<  std::endl; 
-   
- //    std::cout << std::endl; 
- //    sameness(cfp); 
-   
-     // Three std::true_types, and one std::false_type. 
-     std::cout << std::boolalpha << std::endl; 
-     fnarg(GetColor, &i); 
-     fnarg(GetFile, fp); 
-     fnarg(WriteDocument, cfp, cc, b); 
-     fnarg(i); 
-     std::cout << std::noboolalpha << std::endl; 
-   
-     // Return type stuff: 
-     std::cout << "Behold, return type sorcery!" << std::endl; 
-     rtCaller(f1); 
-     rtCaller(f2); 
-     rtCaller(f3); 
-   
- }