#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
};
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 1, int>::type
Get (Ts&&...) { assert(false && "should not be called"); return 0; }
template<typename T>
typename std::enable_if<!std::is_convertible<T, std::string>::value, int>::type
Get (T&&...) { assert(false && "should not be called"); return 0; }
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Post (Ts&&...) { assert(false && "should not be called"); return 0; }
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&&) { assert(false && "should not be called"); return 0; }
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
Delete (Ts&&...) { assert(false && "should not be called"); return 0; }
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&&) { assert(false && "should not be called"); return 0; }
template<typename ... Ts>
typename std::enable_if<sizeof...(Ts) != 2, int>::type
OtherFunc (Ts&&...) { assert(false && "should not be called"); return 0; }
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&&) { assert(false && "should not be called"); return 0; }
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, "hello", MyClass{});
}