在可变参数模板中为每个压缩参数执行函数

时间:2014-12-10 11:51:01

标签: c++ lambda variadic-templates

我注意到开源项目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。

我的问题有两个:

  1. 该线路究竟如何工作?为什么参数解包允许该函数为可变参数模板中的每个参数执行?

  2. 我非常肯定这条线可以用lambda代替。你怎么能用lambda表达式替换这行?

  3. 我已经联系了FeatherKit的原作者,但他当时无法回答我的问题。

1 个答案:

答案 0 :(得分:1)

  
      
  1. 这条线的确如何运作?参数解包如何允许该函数为可变参数模板中的每个参数执行?
  2.   

参数包扩展是一种涉及参数包后跟...

的模式

所以expr(T)...是一个包含expr(T)模式的包扩展,并且对于参数包中的每个expr(T0), expr(T1), expr(T2), ..., expr(TN),它会扩展为Ti

包扩展只能在某些上下文中使用,例如参数列表或初始化列表,因此在这种情况下,每个子表达式的结果用于形成数组int _[]的初始化列表。该数组未使用且仅存在,因此其初始化程序可用作进行包扩展的上下文。每个子表达式都是(SubscribeToType<Ti>(blah, blah), 0)形式,这意味着函数调用的结果被丢弃,表达式的值为0.这是一个允许包扩展产生一个braced-init-的kluge包含N个整数的列表,因为它是初始化数组所需要的。

  
      
  1. 我非常肯定这条线可以用lambda代替。你怎么能用lambda表达式替换这行?
  2.   

你为什么要这样做?

可能,但你需要在lambda中进行非常类似的包扩展,所以它不会简化任何事情。