Home > Blockchain >  Doesn't instance call function to variadic template
Doesn't instance call function to variadic template

Time:11-18

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;
}
  • Related