I am trying to convert a load of classes that are basically the same but take different number of parameters into a single template class. So I have create a template class example (not real code - just for example):
// The template type
template<typename... Args>
class tester_template
{
public:
void process(Args... args)
{
// Create a vector to put the args into. use double since that can hold all of the types
// that I am using (well enough for me anyway). But I get a lot of "narrowing" warnings
// this is understandable, but I want to have no warnings (some sort of cast on a
// parameter pack??)
std::vector<double> args_vect = {args...};
for (auto arg : args_vect)
{
std::cout << arg << " ";
}
std::cout << std::endl;
};
};
I run this like:
// Same with one template class
tester_template<double> template1;
tester_template<int, int> template2;
tester_template<int, int, int> template3;
tester_template<float> template4;
tester_template<float, double, int> template5;
template1.process(1.123); // ok
template2.process(2, 2); // Warnings
template3.process(3, 2, 3); // Warnings
template4.process(4.4f); // Warnings
template5.process(5.5f, 2.234, 3); // Warnings
Full example here with warnings and with example of previous many classes that the template class replaces: https://rextester.com/RBEA68379
So I understand the error/warning message (basically I might lose data if I convert). But I want to inhibit the warnings - perhaps by casting. But I have not a clue how to do this with a parameter pack - maybe I am missing it, but I did not find it online.
Two question I guess:
Yes, you can cast the arguments easily:
std::vector<double> args_vect = {static_cast<double>(args)...};
and there are no warnings emitted.
Here's a demo.
As pointed out in the comments by @NathanOliver, if you just want to print all the variadic arguments, you could do:
void process(Args... args)
{
((std::cout << args << " "), ...);
std::cout << std::endl;
};
Then you don't have to worry about conversions of any kind.
Here's a demo.
You can also use sizeof...
to figure out the number of arguments passed in, and use that information to dispatch to functions that take a fixed number of parameters:
void process1arg(double ) {}
void process2arg(double , double ) {}
void process3arg(double , double , double ) {}
void process(Args... args)
{
((std::cout << args << " "), ...);
std::cout << std::endl;
if constexpr (sizeof...(args) == 1)
process1arg(args...);
if constexpr (sizeof...(args) == 2)
process2arg(args...);
if constexpr (sizeof...(args) == 3)
process3arg(args...);
};
Note that you need if constexpr
and not regular if
, since otherwise the code will not compile when the number of arguments don't match.
Here's a demo.