c++之说_13|模板 折叠表达式
折叠表达式 可以通过形参包的的实际参数(不是类型) 展开式子
这是这里说的几种 实际上并还有一些写法
先介绍这几种吧
#include <cstdio>
template<typename T,T... n>
struct integer_sequence
{
T val;
};
template<int idx,typename _Tulp>
int get(_Tulp& t)
{
return 0;
}
template<typename Ret,typename ...T>
using b = Ret(*)(T...);
b<void,int,int,int,int> _fun;
template<typename ...T>
void getc(T...)
{
}
template<typename T, T... ints>
auto call(integer_sequence<T, ints...> int_seq)
{
T _tuple;
//return getc((get<ints>(_tuple))...);
//return getc(get<ints>(_tuple)...);
//return ((get<ints>(_tuple),...));
//return (ints||...);//一元右折叠
//return (...,ints);//一元左折叠
//return ((5*10)+...+ints);//二元左折叠
//return (ints+...+(5*10));//二元右折叠
}
template<typename ...T>
auto call(T* ... c)//integer_sequence<T*, ints...> int_seq)
{
//return (c -> h,...);
//return (*_fun)(c -> h...);
return (*_fun)( [&](){return c->h; }()...);
// return (c&&...&&0);
}
template<typename T>
struct jk
{
T h;
};
int main()
{
jk<int> b;
b.h = 10;
call(&b,&b,&b,&b);
call(integer_sequence<int, 0,1,2,3>());
}
return (ints||...);//一元右折叠
//return (...,ints);//一元左折叠
// return ((5*10)+...+ints);//二元左折叠
//return (ints+...+(5*10));//二元右折叠
调用处 call(integer_sequence<int, 0,1,2,3>());
我们先看一元右折叠
return (ints||...);//一元右折叠
template<>
bool call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return static_cast<bool>(0) || (static_cast<bool>(1) || (static_cast<bool>(2) || static_cast<bool>(3)));
}
//实例化后是如此
0||
( 1 || ( 2 || 3 )
)
是的外围没有小括号了
一元左折叠
return (...,ints);//一元左折叠
template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return ((0 , 1) , 2) , 3;
}
这个清楚多了
二元左折叠
return ((5*10)+...+ints);//二元左折叠
template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return ((((5 * 10) + 0) + 1) + 2) + 3;
}
二元右折叠
return (ints+...+(5*10));//二元右折叠
template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return 0 + (1 + (2 + (3 + (5 * 10))));
}
好了简单的折叠式子给了
现在我们来看看有点不一样的
----------------------------------------------------
return getc( ( get<ints>(_tuple) )... );
比如这里 我们能看出想法
要根据 形参包实际的参数 ints 去调用并 铺开成为
函数 getc 的参数
如
ints = {0,1};
return getc( (get<0>(_tuple)) , ( get<1>(_tuple)) );
实际上展开呢?
call(integer_sequence<int, 0,1,2,3>());//调用处
template<>
void call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return getc((get<0>(_tuple)), (get<1>(_tuple)), (get<2>(_tuple)), (get<3>(_tuple)));
}
这个和我们之前看到的规则有些不同 什么一元二元 没用到哇
你说括号好多?不和我们平时调用的一样
return getc(get<ints>(_tuple)...);
template<>
void call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return getc(get<0>(_tuple), get<1>(_tuple), get<2>(_tuple), get<3>(_tuple));
}
如此更改 括号没了
这个可以说就是 把 ... 左边的 成一个整体 get<ints>(_tuple)
有前提 必须得是在 类似于函数参数中
return (get<ints>(_tuple)...);
这样写很遗憾是错误的
我们只能使用
一元二元的规则
return (get<ints>(_tuple),...);
template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return get<0>(_tuple) , (get<1>(_tuple) , (get<2>(_tuple) , get<3>(_tuple)));
}
如果这样
return ((get<ints>(_tuple),...));
template<>
int call<int, 0, 1, 2, 3>(integer_sequence<int, 0, 1, 2, 3> int_seq)
{
int _tuple;
return (get<0>(_tuple) , (get<1>(_tuple) , (get<2>(_tuple) , get<3>(_tuple))));
}
外部就会多个括号
-------------------------------------------------------------------------------------------------------------
jk<int> b;
b.h = 10;
call(&b,&b,&b,&b);
//调用处
template<typename ...T>
auto call(T* ... c)//integer_sequence<T*, ints...> int_seq)
{
return (c -> h,...);
//return (*_fun)(c -> h...);
// return (*_fun)( [&](){return c->h; }()...);
// return (c&&...&&0);
}
我们还可以访问类的成员
template<>
int call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
return __c0->h , (__c1->h , (__c2->h , __c3->h));
}
使用函数指针
template<typename Ret,typename ...T>
using b = Ret(*)(T...);
b<void,int,int,int,int> _fun;
return (*_fun)(c -> h...);
template<>
void call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
return (*_fun)(__c0->h, __c1->h, __c2->h, __c3->h);
}
lambda函数
return (*_fun)( [&](){return c->h; }()...);
template<>
void call<jk<int>, jk<int>, jk<int>, jk<int> >(jk<int> * __c0, jk<int> * __c1, jk<int> * __c2, jk<int> * __c3)
{
class __lambda_41_21
{
public:
inline /*constexpr */ int operator()() const
{
return __c0->h;
}
private:
jk<int> & * __c0;
public:
__lambda_41_21(jk<int> & * ___c0)
: __c0{___c0}
{}
} __lambda_41_21{__c0};
class __lambda_41_21
{
public:
inline /*constexpr */ int operator()() const
{
return __c1->h;
}
private:
jk<int> & * __c1;
public:
__lambda_41_21(jk<int> & * ___c1)
: __c1{___c1}
{}
} __lambda_41_21{__c1};
class __lambda_41_21
{
public:
inline /*constexpr */ int operator()() const
{
return __c2->h;
}
private:
jk<int> & * __c2;
public:
__lambda_41_21(jk<int> & * ___c2)
: __c2{___c2}
{}
} __lambda_41_21{__c2};
class __lambda_41_21
{
public:
inline /*constexpr */ int operator()() const
{
return __c3->h;
}
private:
jk<int> & * __c3;
public:
__lambda_41_21(jk<int> & * ___c3)
: __c3{___c3}
{}
} __lambda_41_21{__c3};
return (*_fun)(__lambda_41_21.operator()(), __lambda_41_21.operator()(), __lambda_41_21.operator()(), __lambda_41_21.operator()());
大概就是这样
return (*_fun)( [&](){return c->h; }(),[&](){return c->h; }(),[&](){return c->h; }(),[&](){return c->h; }());
从这里我们也可以看出 lambda 本质是是一个类里面
使用了 operator()
我现所知晓的折叠表达式已经说完了