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!
CodePudding user response:
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;
}