views:

165

answers:

1

Hi All,

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 ?

+9  A: 

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.

GMan
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
@Eternal: yes, you could, but wouldn't it be more interesting to solve a problem rather than reimplement an operator?
Potatoswatter
Variadic templates don't act like LISP… the base case should be the empty list.
Potatoswatter
related http://stackoverflow.com/questions/2771016/why-is-there-a-sizeof-operator-in-c0x
Motti
@Potato: What do you mean? How can one have an empty template list?
GMan
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
As for the difficulty of constructing a function template to match the name `length<>`, can't answer. Maybe avoid overloads here.
Potatoswatter
I imagine you could do `template<typename ... T> constexpr typename enable_if<sizeof...(T)==0, std::size_t>::type length(void) { return 0; }` but i agree - would rather use a class template for that.
Johannes Schaub - litb