8

Suppose I have a variadic template function like

template<typename... Args>
unsigned length(Args... args);

How do I find the length of the parameter list using the length function ?

GManNickG
  • 494,350
  • 52
  • 494
  • 543
Eternal Learner
  • 3,800
  • 13
  • 48
  • 78

1 Answers1

21

Use sizeof...:

template<typename... Args>
constexpr std::size_t length(Args...)
{
    return sizeof...(Args);
}

Note you shouldn't be using unsigned, but std::size_t (defined in <cstddef>). Also, the function should be a constant expression.


Without using sizeof...:

namespace detail
{
    template<typename T>
    constexpr std::size_t length(void)
    {
        return 1; // length of 1 element
    }

    template<typename T, typename... Args>
    constexpr std::size_t length(void)
    {
        return 1 + length<Args...>(); // length of one element + rest
    }
}

template<typename... Args>
constexpr std::size_t length(Args...)
{
    return detail::length<Args...>(); // length of all elements
}

Note, everything is completely untested.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • I was wondering if we could re-curse through the length function, by reducing the size of the template Args in each iteration and having a base case defined when the number of arguments becomes 1. We keep incrementing a counter on each iteration. I am just not able to put my thoughts into code.. – Eternal Learner May 05 '10 at 04:17
  • @Eternal: yes, you could, but wouldn't it be more interesting to solve a problem rather than reimplement an operator? – Potatoswatter May 05 '10 at 04:24
  • Variadic templates don't act like LISP… the base case should be the empty list. – Potatoswatter May 05 '10 at 05:57
  • related http://stackoverflow.com/questions/2771016/why-is-there-a-sizeof-operator-in-c0x – Motti May 05 '10 at 06:23
  • @Potato: What do you mean? How can one have an empty template list? – GManNickG May 05 '10 at 06:39
  • The parameter pack can match the empty list. `sizeof ...` can return 0. 14.3/1: "When the parameter declared by the template is a template parameter pack (14.5.3), it will correspond to zero or more template-arguments." – Potatoswatter May 05 '10 at 06:53
  • As for the difficulty of constructing a function template to match the name `length<>`, can't answer. Maybe avoid overloads here. – Potatoswatter May 05 '10 at 06:59
  • I imagine you could do `template constexpr typename enable_if::type length(void) { return 0; }` but i agree - would rather use a class template for that. – Johannes Schaub - litb May 05 '10 at 21:21