Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixed Length Variadic Parameter Packs in C++11

I'm attempting to implement a generalized n-dimensional vector class using C++11. Ideally, I'd like to provide the type "T" and number of dimensions "n" of the vector and have the constructor accept the appropriate number of arguments.

Unfortunately, I've been unable to find a way to allow a template-specified fixed length of a parameter pack.

What I'm looking for is something like

template<typename T, size_t n>
class Vector {
public:
    Vector(T... values /* values is exactly n parameters long */);

    ...
};

Is it possible to do this?

like image 773
Joe Babb Avatar asked Jul 09 '14 19:07

Joe Babb


2 Answers

Well, you can use std::enable_if:

template <typename... Args,
    typename = typename std::enable_if<
        sizeof...(Args) == n
    >::type>
explicit Vector(Args&&... values) : _data{ std::forward<Args>(values)... } {}

It will shadow constructors that may accept size of Args other than n.

like image 80
Garrappachc Avatar answered Nov 14 '22 20:11

Garrappachc


You could also use this trick:

template <typename T, std::size_t n, typename = std::make_index_sequence<n>>
class Vector;

template <typename T, std::size_t n, std::size_t... Ignore>
class Vector<T, n, std::index_sequence<Ignore...>>
{
    template <size_t > using ith_T = T;
public:
    Vector(ith_T<Ignore>... values)
    {
    }
};

This will ensure that Vector takes n arguments of type T, no additional templating necessary. You could additionally hide the Ignore... ugliness in a namespace:

namespace details {
    template <typename T, std::size_t n, typename = std::make_index_sequence<n>>
    class Vector;

    ...
}

template <typename T, std::size_t n>
using Vector = details::Vector<T, n>;
like image 43
Barry Avatar answered Nov 14 '22 21:11

Barry