I have write function to deduce how much parameters I forward to function. Something like this:
template<typename Arg>
constexpr size_t get_init_size(Arg arg, size_t i) {
return i + 1;
}
template<typename T, typename ... Args>
constexpr size_t get_init_size(T First_arg, Args ... args, size_t i) {
return get_init_size(args... , i + 1);
}
auto create_ipv4_header() {
size_t x = get_init_size(0b01, 0b10, 0b01, static_cast<size_t>(0));
return x //<= must return 3
}
But compiler write:
error: no matching function for call to ‘get_init_size(int, int, int, size_t)’
So it is problem in variadic template? And one more thing if I change variadic template to something like this:
template<typename T, typename ... Args>
constexpr size_t get_init_size(T First_arg, Args ... args, size_t i = 0)
I can put down last parameter?(I doesn’t test it with variadic template) Thanks for help!
>Solution :
You don’t need to write a recursive template function to do this, you can use the sizeof...() operator on the type of the parameter pack to get the number of elements directly:
template<typename... Args>
constexpr std::size_t get_init_size(Args&&...) {
return sizeof...(Args);
}
See it in action here.
The reason why your function doesn’t work is because a parameter pack is deduced greedily; meaning Args... args matches 0b10, 0b01 and static_cast<size_t>(0). Then because there is no argument matching the size_t i anymore, substitution fails and the only candidate left is the first version of get_init_size(), which of course also is not a match. It’s always hard or impossible to have extra parameters after a parameter pack. You could move size_t i to the front though. Another approach is to not pass i as a parameter, but add + 1 to the return value instead:
template<typename Arg>
constexpr std::size_t get_init_size(Arg&&) {
return 1;
}
template<typename T, typename... Args>
constexpr std::size_t get_init_size(T&&, Args&&... args) {
return get_init_size(args...) + 1;
}