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