问题描述:

Trying to search for this answer, I noticed that the titles of the questions

on variadic template functions are very uninformative when searching on

SO. You only known that the question is about variadic template. Hopefully my

question wasn't asked before and the title will help people finding it.

So, I want to make a function which has a variadic template parameter. More

precisely, as an example, let say I want to have a compile time permutation of

an array. Here is a working code:

`template <typename... Ts> struct Sequence {};`

template <typename T, unsigned Size, typename... SeqTis> struct Permute;

template <typename T, unsigned Size, typename... SeqTis>

struct Permute<T, Size, Sequence<SeqTis...> > {

using type = typename std::array<T, Size>;

constexpr static type permute(const type ar) {

return { (ar[SeqTis::value])... };

}

};

Then the following is perfectly legal:

`using T0 = std::integral_constant<int, 0>;`

using T1 = std::integral_constant<int, 1>;

using T2 = std::integral_constant<int, 2>;

using Perm120 = Permute<int, 3, Sequence<T1, T2, T0> >;

using arr3 = Perm120::type;

constexpr arr3 ar {5,7,2};

constexpr arr3 arPerm = Perm120::permute(ar);

I'm now trying to avoid using a structure so I wrote the following:

`template <typename T, unsigned Size, typename... SeqTis>`

constexpr typename std::array<T, Size>

permutefun<T, Size, Sequence<SeqTis...> >(const typename std::array<T, Size> ar) {

return { (ar[SeqTis::value])... };

}

And GCC refuse it saying that

`essai.cpp:19:11: error: expected initializer before ‘<’ token`

permutefun<T, Size, Sequence<SeqTis...> >(const typename std::array<T, Size> ar) {

^

Why is it so ?

To add to previous answers, you also need to have a convenient syntax for calling `permutefun`

, but the current template parameters

```
template <typename T, unsigned Size, typename... SeqTis>
```

are not convenient because you'd have to call

```
permutefun <int, 3, T1, T2, T0>(ar);
```

A solution is to deduce arguments in two steps:

```
#include <array>
template <typename... Ts> struct Sequence {};
template <typename... SeqTis, typename T, unsigned long Size>
constexpr std::array<T, Size>
permutefun(Sequence<SeqTis...>, const std::array<T, Size> ar) {
return { (ar[SeqTis::value])... };
}
template <typename Seq, typename T, unsigned long Size>
constexpr std::array<T, Size>
permutefun(const std::array<T, Size> ar) {
return permutefun(Seq(), ar);
}
int main ()
{
using T0 = std::integral_constant<int, 0>;
using T1 = std::integral_constant<int, 1>;
using T2 = std::integral_constant<int, 2>;
using Perm120 = Sequence<T1, T2, T0>;
using arr3 = std::array <int, 3>;
constexpr arr3 ar = {5,7,2};
constexpr arr3 arPerm = permutefun <Perm120>(ar);
}
```

Now arguments `T, Size`

appear last so are automatically deduced by the input array. Argument `Seq`

comes first, but to deduce its "unpacked" parameters `SeqTis...`

you need a call to a second overload of `permutefun`

. This allows the convenient syntax

```
permutefun <Perm120>(ar);
```

The 2nd overload may be useful by itself, because it allows the alternative syntax

```
Perm120 perm;
permutefun(perm, ar);
```

Also note that `std::array::operator[]`

is `constexpr`

only in C++14. For instance, this does not compile with Clang 3.3 and `-std=c++11`

.

Your syntax looks like an attempt at a partial function specialisation, but that's not what you want, so that's not what you should write. Since partial function specialisations aren't supported, the compiler gets confused by the unexpected `<`

.

```
template <typename T, unsigned Size, typename... SeqTis>
constexpr std::array<T, Size>
permutefun(const std::array<T, Size> ar) {
// ^ removed the <...>
return { (ar[SeqTis::value])... };
}
```

Also, you don't need `typename`

here, as `std::array<T, Size>`

is already known to be a type. It's fine to leave it in, but it works just as well without it.

Do you mean:

```
template <typename T, unsigned Size, typename... SeqTis>
constexpr std::array<T, Size>
permutefun(const typename std::array<T, Size> ar) {
return { (ar[SeqTis::value])... };
}
```

partial template specialization is not possible for function.