在可变参数模板函数中避免结构体 [英] Avoiding struct in variadic template function

查看:235
本文介绍了在可变参数模板函数中避免结构体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试着搜索这个答案,我注意到在
SO上搜索时,可变参数模板函数上的问题
的标题是非常无用的。你只知道这个问题是关于variadic模板的。希望我的
问题以前没有问过,标题将帮助人们找到它。



所以,我想创建一个具有可变参数模板参数的函数。作为一个例子,更准确地说,我假设我想要一个数组
的编译时间排列。这是一个工作代码:

 模板< typename ... Ts> struct Sequence {}; 

模板< typename T,无符号大小,类型名称... SeqTis> struct Permute;

模板< typename T,无符号大小,类型名称... SeqTis>
struct Permute< T,Size,Sequence< SeqTis ...> > {
使用type = typename std :: array< T,Size>;
constexpr static type permute(const type ar){
return {(ar [SeqTis :: value])...};
}
};

然后以下内容完全合法:

 使用T0 = std :: integral_constant< int,0>; 
使用T1 = std :: integral_constant< int,1>;
使用T2 = std :: integral_constant< int,2>;
使用Perm120 = Permute 取代;
使用arr3 = Perm120 :: type;
constexpr arr3 ar {5,7,2};
constexpr arr3 arPerm = Perm120 :: permute(ar);

我现在试图避免使用结构,所以我写了下面的代码:

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

而GCC拒绝它说

  essai.cpp:19:11:错误:'<'令牌之前的预期初始化器
permutefun< T,大小,序列< SeqTis ...> >(const typename std :: array< T,Size> ar){
^

为什么会这样?

解决方案

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

 模板< typename T,unsigned Size, typename ... SeqTis> 

不方便,因为您必须致电

  permutefun (ar); 

一个解决方案是分两步推导参数:

  #include< array> 

模板< typename ... Ts> struct Sequence {};

模板< 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])...};
}

模板< 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> ;;
使用T1 = std :: integral_constant< int,1>;
使用T2 = std :: integral_constant< int,2>;

使用Perm120 =序列< T1,T2,T0>;
使用arr3 = std :: array< int,3>;
constexpr arr3 ar = {5,7,2};
constexpr arr3 arPerm = permutefun< Perm120>(ar);

$ / code>

现在参数 T,大小最后出现,所以会自动由输入数组推导出来。参数 Seq 是第一个,但要推断其解包参数 SeqTis ... ,您需要调用第二个参数超载 permutefun 。这允许方便的语法

  permutefun< Perm120>(ar); 

第二次重载本身很有用,因为它允许使用替代语法

  Perm120 perm; 
permutefun(perm,ar);

还要注意 std :: array :: operator [] 仅在C ++ 14中 constexpr 。例如,这不会在Clang 3.3和 -std = c ++ 11 中编译。


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.

这篇关于在可变参数模板函数中避免结构体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆