我注意到开源项目FeatherKit中的以下行:
int _[] = { (SubscribeToType<MessageTypes>( bus, receiver, desubscribers, unsubscribe ), 0)... };
具有以下背景:
template<class... MessageTypes>
void Subscribe( MessageBus& bus, MessageReceiver<MessageTypes...>& receiver, bool unsubscribe ) {
std::vector<std::function<void()>> desubscribers;
int _[] = { (SubscribeToType<MessageTypes>( bus, receiver, desubscribers, unsubscribe ), 0)... };
(void) _;
receiver.desubscribers = desubscribers;
}
显然,为可变参数模板中的每个参数执行函数SubscribeToType。
我的问题有两个:
该线路究竟如何工作?为什么参数解包允许该函数为可变参数模板中的每个参数执行?
我非常肯定这条线可以用lambda代替。你怎么能用lambda表达式替换这行?
我已经联系了FeatherKit的原作者,但他当时无法回答我的问题。
答案 0 :(得分:1)
- 这条线的确如何运作?参数解包如何允许该函数为可变参数模板中的每个参数执行?
醇>
参数包扩展是一种涉及参数包后跟...
所以expr(T)...
是一个包含expr(T)
模式的包扩展,并且对于参数包中的每个expr(T0), expr(T1), expr(T2), ..., expr(TN)
,它会扩展为Ti
。
包扩展只能在某些上下文中使用,例如参数列表或初始化列表,因此在这种情况下,每个子表达式的结果用于形成数组int _[]
的初始化列表。该数组未使用且仅存在,因此其初始化程序可用作进行包扩展的上下文。每个子表达式都是(SubscribeToType<Ti>(blah, blah), 0)
形式,这意味着函数调用的结果被丢弃,表达式的值为0.这是一个允许包扩展产生一个braced-init-的kluge包含N个整数的列表,因为它是初始化数组所需要的。
- 我非常肯定这条线可以用lambda代替。你怎么能用lambda表达式替换这行?
醇>
你为什么要这样做?
可能,但你需要在lambda中进行非常类似的包扩展,所以它不会简化任何事情。