#include <array>
#include <type_traits>
#include <iostream>
template<class... Types>
class Test {
public:
Test()
: format_({
[&] {
if constexpr(std::is_same_v<Types, int64_t>) {
return "%ld ";
} else if constexpr(std::is_same_v<Types, int32_t>) {
return "%d ";
} else if constexpr(std::is_same_v<Types, double>) {
return "%f ";
}
}() ...
}) {}
template<typename T, typename ... Args>
void print_recursive(T && v, Args && ... args) {
size_t i = sizeof...(Types) - sizeof...(args) - 1;
printf(format_[i], std::forward<T>(v));
if constexpr(sizeof...(Args) > 0) {
print_recursive(std::forward<Args>(args)...);
} else {
printf("\n");
}
}
void print_fold(Types && ... args) {
size_t i = 0;
([&]{
printf(format_[i ], args);
}(), ...);
printf("\n");
}
private:
std::array<const char*, sizeof...(Types)> format_;
};
int main() {
Test<int64_t, int32_t, double> t;
t.print_recursive(1.0, 2, 3.0);
t.print_fold(1.0, 2, 3.0);
}
OUTPUT:
0 2 3.000000
1 2 3.000000
Built and ran with the following:
g test.cpp -o test -std=c 17 && ./test
Compiler Info:
$ gcc --version
gcc (GCC) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
In the above example, the format_
array is defined using fold expressions and used in both print calls. Each print call has the same format specifier for the same index. Each print call has the same args past to it as well. However the output is different for the two. Why is that the case?
EDIT: Adding the correct recursive call that will convert the function arguments to the class template types first before making the recursive call as recommended by @n. m.
void print_recursive(Types && ... args) {
print_recursive_impl(std::forward<Types>(args)...);
}
template<typename T, typename ... Args>
void print_recursive_impl(T && v, Args && ... args) {
size_t i = sizeof...(Types) - sizeof...(args) - 1;
printf(format_[i], std::forward<T>(v));
if constexpr(sizeof...(Args) > 0) {
print_recursive_impl(std::forward<Args>(args)...);
} else {
printf("\n");
}
}
CodePudding user response:
You print double as an integer in the recursive call. That's a UB or some other nonsense.
In the fold version you convert them to the appropriate types first.