#include <cstdio>
#include <string>
#include <tuple>
#include <utility>
template <typename T>
struct get_specifier;
template <>
struct get_specifier<int> {
static constexpr char const* value = "%d";
};
template <>
struct get_specifier<char const*> {
static constexpr char const* value = "%s";
};
template <>
struct get_specifier<double> {
static constexpr char const* value = "%f";
};
template <size_t, typename>
struct format_runner;
template <size_t Index, typename... Ts>
struct format_runner<Index, std::tuple<Ts...>> {
using tuple_type = std::tuple<Ts...>;
template <typename String>
static String execute(String&& init) {
return format_runner<Index-1, tuple_type>::execute(std::forward<String>(init))
+ " "
+ get_specifier<
typename std::tuple_element<Index, tuple_type>::type
>::value;
}
};
template <typename... Ts>
struct format_runner<0, std::tuple<Ts...>> {
using tuple_type = std::tuple<Ts...>;
template <typename String>
static String execute(String&& init) {
return init + get_specifier<
typename std::tuple_element<0, tuple_type>::type
>::value;
}
};
template <typename String, typename... Ts>
String format(String&& init, Ts&&... values) {
return format_runner<
sizeof...(Ts)-1,
std::tuple<typename std::remove_reference<Ts>::type...>
>::execute(std::forward<String>(init));
}
template <typename... Ts>
int redisCommand(char const* prefix, Ts&&... values) {
return std::printf(
format(std::string(prefix), values...).c_str(),
values...
);
}
int main() {
char const* value1 = "1";
int value2 = 2;
double value3 = 3.0;
redisCommand("SET foo ", value1, value2, value3);
}
I2luY2x1ZGUgPGNzdGRpbz4KCiNpbmNsdWRlIDxzdHJpbmc+CiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPHV0aWxpdHk+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IGdldF9zcGVjaWZpZXI7Cgp0ZW1wbGF0ZSA8PgpzdHJ1Y3QgZ2V0X3NwZWNpZmllcjxpbnQ+IHsKICAgIHN0YXRpYyBjb25zdGV4cHIgY2hhciBjb25zdCogdmFsdWUgPSAiJWQiOwp9OwoKdGVtcGxhdGUgPD4Kc3RydWN0IGdldF9zcGVjaWZpZXI8Y2hhciBjb25zdCo+IHsKICAgIHN0YXRpYyBjb25zdGV4cHIgY2hhciBjb25zdCogdmFsdWUgPSAiJXMiOwp9OwoKdGVtcGxhdGUgPD4Kc3RydWN0IGdldF9zcGVjaWZpZXI8ZG91YmxlPiB7CiAgICBzdGF0aWMgY29uc3RleHByIGNoYXIgY29uc3QqIHZhbHVlID0gIiVmIjsKfTsKCnRlbXBsYXRlIDxzaXplX3QsIHR5cGVuYW1lPgpzdHJ1Y3QgZm9ybWF0X3J1bm5lcjsKCnRlbXBsYXRlIDxzaXplX3QgSW5kZXgsIHR5cGVuYW1lLi4uIFRzPgpzdHJ1Y3QgZm9ybWF0X3J1bm5lcjxJbmRleCwgc3RkOjp0dXBsZTxUcy4uLj4+IHsKICAgIHVzaW5nIHR1cGxlX3R5cGUgPSBzdGQ6OnR1cGxlPFRzLi4uPjsKICAgIAogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFN0cmluZz4KICAgIHN0YXRpYyBTdHJpbmcgZXhlY3V0ZShTdHJpbmcmJiBpbml0KSB7CiAgICAgICAgcmV0dXJuIGZvcm1hdF9ydW5uZXI8SW5kZXgtMSwgdHVwbGVfdHlwZT46OmV4ZWN1dGUoc3RkOjpmb3J3YXJkPFN0cmluZz4oaW5pdCkpCiAgICAgICAgICAgICAgICsgIiAiCiAgICAgICAgICAgICAgICsgZ2V0X3NwZWNpZmllcjwKICAgICAgICAgICAgICAgICAgdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PEluZGV4LCB0dXBsZV90eXBlPjo6dHlwZQogICAgICAgICAgICAgICA+Ojp2YWx1ZTsKICAgIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZS4uLiBUcz4Kc3RydWN0IGZvcm1hdF9ydW5uZXI8MCwgc3RkOjp0dXBsZTxUcy4uLj4+IHsKICAgIHVzaW5nIHR1cGxlX3R5cGUgPSBzdGQ6OnR1cGxlPFRzLi4uPjsKICAgIAogICAgdGVtcGxhdGUgPHR5cGVuYW1lIFN0cmluZz4KICAgIHN0YXRpYyBTdHJpbmcgZXhlY3V0ZShTdHJpbmcmJiBpbml0KSB7CiAgICAgICAgcmV0dXJuIGluaXQgKyBnZXRfc3BlY2lmaWVyPAogICAgICAgICAgICAgICAgICB0eXBlbmFtZSBzdGQ6OnR1cGxlX2VsZW1lbnQ8MCwgdHVwbGVfdHlwZT46OnR5cGUKICAgICAgICAgICAgICAgPjo6dmFsdWU7CiAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgU3RyaW5nLCB0eXBlbmFtZS4uLiBUcz4KU3RyaW5nIGZvcm1hdChTdHJpbmcmJiBpbml0LCBUcyYmLi4uIHZhbHVlcykgewogICAgcmV0dXJuIGZvcm1hdF9ydW5uZXI8CiAgICAgICAgc2l6ZW9mLi4uKFRzKS0xLAogICAgICAgIHN0ZDo6dHVwbGU8dHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPFRzPjo6dHlwZS4uLj4KICAgID46OmV4ZWN1dGUoc3RkOjpmb3J3YXJkPFN0cmluZz4oaW5pdCkpOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gVHM+CmludCByZWRpc0NvbW1hbmQoY2hhciBjb25zdCogcHJlZml4LCBUcyYmLi4uIHZhbHVlcykgewogICAgcmV0dXJuIHN0ZDo6cHJpbnRmKAogICAgICAgIGZvcm1hdChzdGQ6OnN0cmluZyhwcmVmaXgpLCB2YWx1ZXMuLi4pLmNfc3RyKCksCiAgICAgICAgdmFsdWVzLi4uCiAgICApOwp9CgppbnQgbWFpbigpIHsKICAgIGNoYXIgY29uc3QqIHZhbHVlMSA9ICIxIjsKICAgIGludCB2YWx1ZTIgPSAyOwogICAgZG91YmxlIHZhbHVlMyA9IDMuMDsKICAgIAogICAgcmVkaXNDb21tYW5kKCJTRVQgZm9vICIsIHZhbHVlMSwgdmFsdWUyLCB2YWx1ZTMpOwp9