1

I want to make a variadic template with exactly N arguments, where N is also a template parameter. For example,

template <int N, typename T[N]>
void function(T t[N]) {
    // do stuff with t[0] through t[N-1]
}

(I realize the above is not valid syntax)

I know that one way to achieve this is to use a static_assert on sizeof...(ArgsT) where ArgsT is a variadic template definition (i.e. template <typename ...ArgsT>).

I am just wondering if there is a better way, not necessarily involving static_assert.

  • 2
    static_assert is already a nice failing of compilation (stick to it) –  May 04 '14 at 16:16
  • 1
    In summary, you want a compile time error when the pack size does not equal the int parameter ? `static_assert` is meant for this, why wouldn't it be the best way ? – Chnossos May 04 '14 at 16:16
  • 1
    You may also use SFINAE with `std::enable_if`. But I'm not sure it is better. – Jarod42 May 04 '14 at 16:21
  • 1
    @Jarod42: The difference is whether you want the overloads to *exist*. Unless it's important not to pollute the overload set, a static assertion may produce easier diagnostics. – Kerrek SB May 04 '14 at 16:30

1 Answers1

6

You can use std::enable_if instead of static_assert:

template <std::size_t N, typename ...Args>
auto function(Args&&... args)
    -> typename std::enable_if<N == sizeof...(Args), void>::type
{
    ...
}

Update: It's also possible to use it in constructors, where N is a template argument of the class.

template <std::size_t N>
struct foobar
{
    template <typename ...Args, typename = typename std::enable_if<N == sizeof...(Args), void>::type>
    foobar(Args&&... args) { ... }
};
Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63
nosid
  • 48,932
  • 13
  • 112
  • 139