Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Doesn't instance call function to variadic template

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!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading