C++ 可变模板函数中的结构避免

C++ 可变模板函数中的结构避免,c++,function,c++11,struct,variadic-templates,C++,Function,C++11,Struct,Variadic Templates,试图寻找这个答案,我注意到问题的标题 在上搜索时,可变模板函数非常缺乏信息 所以你只知道这个问题是关于变量模板的。希望我的 这个问题以前并没有被问过,标题将帮助人们找到它 所以,我想做一个具有可变模板参数的函数。更多 确切地说,作为一个例子,假设我想要一个 数组。以下是工作代码: template <typename... Ts> struct Sequence {}; template <typename T, unsigned Size, typename... SeqT

试图寻找这个答案,我注意到问题的标题 在上搜索时,可变模板函数非常缺乏信息 所以你只知道这个问题是关于变量模板的。希望我的 这个问题以前并没有被问过,标题将帮助人们找到它

所以,我想做一个具有可变模板参数的函数。更多 确切地说,作为一个例子,假设我想要一个 数组。以下是工作代码:

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])... };
  }
};
那么以下是完全合法的:

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);
我现在试图避免使用结构,因此我写了以下内容:

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])... };
}
海湾合作委员会拒绝这样说

essai.cpp:19:11: error: expected initializer before ‘<’ token
  permutefun<T, Size, Sequence<SeqTis...> >(const typename std::array<T, Size> ar) {
           ^

为什么会这样?

您的语法看起来像是试图对部分函数进行专门化,但这并不是您想要的,因此您不应该这样写。由于不支持部分函数专门化,编译器会被意外的问题弄糊涂。您的意思是:

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

部分模板专用化对于函数是不可能的。

要添加到前面的答案中,您还需要有一个方便的语法来调用permutefun,但是当前模板参数

template <typename T, unsigned Size, typename... SeqTis>
第二个重载本身可能很有用,因为它允许使用其他语法

Perm120 perm;
permutefun(perm, ar);

还要注意,std::array::operator[]仅在C++14中是constexpr。例如,它不能用clang3.3和-std=c++11编译。

Ok!看起来我真的不明白什么是部分模板专门化。无论如何,谢谢你的回答。@hivert部分专门化就是你在问题中的类型。模板结构置换;然后是模板结构置换。这是一个专门化,但它不是一个完全的专门化,因为专门化本身依赖于其他模板类型参数;不是部分专业化,因此是允许的。对吗?@hivert确实如此。这将是一个完全的专业化,甚至在函数中也是可能的。酷!诀窍是将结构作为伪参数传递给函数,而不是作为模板。顺便说一句,你不再需要struct Permute了,我允许自己删除这行。谢谢!额外的参数并不是真正的伪参数——它通过其类型传递一些信息,因此可以看作是模板参数。这类似于将函数对象作为参数传递,如std::less。我还从std::array中删除了typename,如@hvd所述。顺便说一句,如果序列仅用于此目的,则有一个更简单的定义模板struct Sequence{};。然后可以直接使用Perm120=序列,而不定义T0、T1、T2。在这种情况下,Sektis将变为size\u t。。。和作为ar[SeqTis]访问的数组元素。。。。
permutefun <int, 3, T1, T2, T0>(ar);
#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);
}
permutefun <Perm120>(ar);
Perm120 perm;
permutefun(perm, ar);