Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A variadic function that accepts Strings and Ints, Format the latter and concatenate all?

I'm trying to use the answer from DanielKO in this question for my needs but i'm not familiar with templates and variadic functions, and i don't get what should i do.

What i'd need is a variadic c++(11) function which i can call like this:

 String NewMsg = CreateMessage("SET",16,1,17,0,"RED",47);

and have NewMsg= "SET,0010,0001,0011,0000,RED,002F".

I'm not even able to get where should i add the comma between the arguments. And then: How could i distinguish between integers and string while parsing the args, so to format each integer to hexadecimal strings?

like image 669
Parduz Avatar asked Jan 28 '19 14:01

Parduz


People also ask

What symbols are used in a function declaration to indicate that it is a Variadic function?

A function with a parameter that is preceded with a set of ellipses ( ... ) is considered a variadic function. The ellipsis means that the parameter provided can be zero, one, or more values. For the fmt. Println package, it is stating that the parameter a is variadic.

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.


2 Answers

You use recursion and function overloading

std::string CreateMessage(int i)
{
    return /* i formatted as hex */;
}

std::string CreateMessage(const char* s)
{
    return s;
}

template<typename T, typename... Ts>
std::string CreateMessage(T t, Ts... ts)
{
    return CreateMessage(t) + "," + CreateMessage(ts...);
}
like image 113
Passer By Avatar answered Nov 10 '22 13:11

Passer By


One option is to use recursion with templates, as Passer By did in his answer. However, in my opinion a more elegant solution (if you are able to use C++17 lanugage features) is to use a fold expression to avoid recursion. The expression is expanded such that Append is called directly for each argument, sort of like a for-loop across the arguments evaluated at compile time.

template <class T>
void Append(std::ostringstream &out, T &&arg) {
    out << "," << std::forward<T>(arg);
}

template <class... TArgs>
std::string CreateMessage(TArgs &&...args) {
    std::ostringstream out;
    (Append(out, std::forward<TArgs>(args)), ...);
    return out.str().substr(1);
}

Live demo here.

like image 27
Nick Mertin Avatar answered Nov 10 '22 14:11

Nick Mertin