Reputation: 353
Imagine I have two functions:
void string(const char *str)
{
std::cout << "this is string" << std::endl;
}
void number(const char *str, double f)
{
std::cout << "this is number" << std::endl;
}
I want to write a generic wrapper so that be able to call format()
like this:
int main() {
format("single arg");
format("format string", 1.0);
format("single arg", "format string", 1.0);
format("format string 1", 1.0, "just string arg", "format string 2", 2.0);
return 0;
}
That is if arguments come in pair {string, number}, then invoke number()
; otherwise call string()
. Obviously, it can be done only unpacking arguments right-to-left. I've tried to implement it following (wrong) way:
template<class T>
void operation(T first)
{
string(first);
}
template<class T, class U = float>
void operation(T first, U second)
{
number(first, second);
}
template<class ... ARGS>
void format(ARGS ... args)
{
auto last = (args, ...);
using last_type = typename decltype(last);
if constexpr (std::is_arithmetic_v<last_type>)
(..., operation(args, last));
else
(..., operation(args));
}
The problem is that while unpacking operation(args, last)
we will get both args
and last
floats. I believe there's some easy way to achieve what I want (without relying on tuples etc).
Upvotes: 1
Views: 76
Reputation: 63114
Here is a proof-of-concept using only overload resolution. I'm not sure how scalable it is, though.
void format() {}
void format(char const *str) {
string(str);
}
template <class... Args>
void format(char const *str, char const *nextStr, Args... args);
template <class... Args>
void format(char const *str, double f, Args... args);
template <class... Args>
void format(char const *str, char const *nextStr, Args... args) {
string(str);
format(nextStr, args...);
}
template <class... Args>
void format(char const *str, double f, Args... args) {
number(str, f);
format(args...);
}
Upvotes: 5