#include <cassert>
#include <memory>
#include <sstream>
#include <string>
#include <iostream>
class MyClass {};
bool Post(std::string /*command*/, std::string /*payload*/) { std::cout << "Post\n"; return false;}
std::string Get(std::string /*command*/) { std::cout << "Get\n"; return ""; }
bool Delete(std::string /*command*/, std::string /*name*/) { std::cout << "Delete\n"; return false;}
int OtherFunc(std::string /*command*/, const MyClass& /*name*/) { std::cout << "OtherFunc\n"; return 0;}
enum class CommandType
{
Get, Post, Delete, OtherFunc
};
#define Stringify( T ) #T
#define MakeString( M, L ) M(L)
#define $Line MakeString( Stringify, __LINE__ )
#define TemplateErrMsg __FILE__ "(" $Line ") : Invalid template used:" MakeString( Stringify, __FUNCTION__ )
#define DO_PRAGMA(x) _Pragma ( #x )
#define INVALID_TEMPLATE {DO_PRAGMA(message(TemplateErrMsg)); assert( false && TemplateErrMsg ); return 0; }
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 1, int>::type
Get (Ts&&...) INVALID_TEMPLATE
template<typename T>
typename std::enable_if<!std::is_convertible<T, std::string>::value, int>::type
Get (T&&...) INVALID_TEMPLATE
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Post (Ts&&...) INVALID_TEMPLATE
template<typename T1, typename T2>
typename std::enable_if<!std::is_convertible<T1, std::string>::value
|| !std::is_convertible<T2, std::string>::value,
int>::type
Post (T1&&, T2&&) INVALID_TEMPLATE
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Delete (Ts&&...) INVALID_TEMPLATE
template<typename T1, typename T2>
typename std::enable_if<!std::is_convertible<T1, std::string>::value
|| !std::is_convertible<T2, std::string>::value,
int>::type
Delete (T1&&, T2&&) INVALID_TEMPLATE
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
OtherFunc (Ts&&...) INVALID_TEMPLATE
template<typename T1, typename T2>
typename std::enable_if<!std::is_convertible<T1, std::string>::value
|| !std::is_convertible<T2, const MyClass&>::value,
int>::type
OtherFunc (T1&&, T2&&) INVALID_TEMPLATE
template<typename... Ts>
std::unique_ptr<std::stringstream>
Execute(CommandType command, Ts&&... parameters) {
auto response = std::make_unique<std::stringstream>();
if(command == CommandType::Get)
*response << Get(std::forward<Ts>(parameters)...);
else if(command == CommandType::Post)
*response << Post(std::forward<Ts>(parameters)...);
else if(command == CommandType::Delete)
*response << Delete(std::forward<Ts>(parameters)...);
else if(command == CommandType::OtherFunc)
*response << OtherFunc(std::forward<Ts>(parameters)...);
return response;
}
int main(){
Execute(CommandType::Get, "hello");
Execute(CommandType::Post, "hello", "world");
Execute(CommandType::Delete, "hello", "world");
Execute(CommandType::OtherFunc , 123, "test", MyClass{});
}