Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C++;行动方式功能?_C#_C++_C++11_Lambda_Action - Fatal编程技术网

C# C++;行动方式功能?

C# C++;行动方式功能?,c#,c++,c++11,lambda,action,C#,C++,C++11,Lambda,Action,在C中,我们可以说: Action act = ()=> {/*stuff*/}; act += ()=> {/*another stuff*/}` 然后调用act() 我想知道C++中如何做这样的事情(现在用lambdas它会非常有用,如果可能的话不使用Booost /Qt信号), 你可以很容易地写下这样的东西,用lambdas填充:vector < /代码>,调用每个函数对象。 #include <vector> #include <functional&

在C中,我们可以说:

Action act = ()=> {/*stuff*/}; 
act += ()=> {/*another stuff*/}` 
然后调用
act()


<>我想知道C++中如何做这样的事情(现在用lambdas它会非常有用,如果可能的话不使用Booost /Qt信号),

你可以很容易地写下这样的东西,用lambdas填充<代码>:vector < /代码>,调用每个函数对象。
#include <vector>
#include <functional>
#include <utility>

// warning: very crude and likely with typos / bugs
template<class Sig>
struct Action{
  template<typename Functor>
  void operator+=(Functor&& f)
  { _funcs.emplace_back(std::forward<Functor>(f)); }
  template<class... Args>
  void operator()(Args&&... args) const{
    for(auto& f : _funcs)
      f(args...);
  }
private:
  std::vector<std::function<Sig>> _funcs;
};

// ...
Action<void()> act;
act += []{ /*...*/ };
act += []{ /*...*/ };
act(); // invoke all handlers in order
#包括
#包括
#包括
//警告:非常粗糙,可能有打字错误/错误
模板
结构动作{
模板
void运算符+=(函子(&f)
{u funcs.emplace_back(std::forward(f));}
模板
void运算符()(Args&&…Args)常量{
对于(自动和f:_funcs)
f(args…);
}
私人:
std::vector_funcs;
};
// ...
行动法;
act+=[]{/*…*/};
act+=[]{/*…*/};
act();//按顺序调用所有处理程序

不过,从我所知道的,C++也允许您删除一个处理程序,使用<代码> -= ,这在C++中不容易实现。您需要从

+=
返回一个令牌,该令牌可以传递到
-=
以删除特定的处理程序。

可能使用
std::function
s:

std::vector<std::function<void()>> act;

act.emplace_back([] { /* stuff */ });
act.emplace_back([] { /* more stuff */ });

+=
到底做了什么(对于那些不懂C#的人来说)?@Xeo它为委托方法添加了另一个处理程序。@Richard:还有。。。然后调用委托时会发生什么?它是否按顺序执行所有处理程序?它是否会将早期处理程序的结果传递给下一个处理程序?是否会有点鲁莽地多次转发某些内容?您可以使用
操作符-=
,强制它们使用相同的对象,我认为这正是C所需要的。毕竟,如果不进行昂贵的字节码比较,它怎么知道其他匿名lambda表达式是等价的呢?@KerrekSB:Ooh,我明白了。是 啊请参见课程上方的警告。:>简单地不转发它们应该“起作用”。@pickypg:Lambda对象以及
std::function
不提供比较运算符,因为实际上不可能定义什么是“相等”。您可以使用对象地址,但对于lambda,每个lambda表达式都有一个唯一的对象和类型。@Kerrek:我真的不认为这里有“最佳”选择,因为可能需要左值传递,您可能希望将更新传播到其他处理程序。如果有人使用了自己的
操作
类,您可以像Xeo下面所做的那样轻松地实现
操作符+=
(仅使用
std::function
),并且它将非常匹配。为什么不
推回
?:)<代码>安放(_xxx)
用于安放构造,只是表示不同的目的。@Xeo:安放是新的通用方式。由于放置构造函数包含复制构造函数(但也允许移动!),因此无需携带旧的积木。嗯,
push_back
有一个右值重载。:)我认为这只是功能最初设计的不同目的。另外,我认为
emplace
允许
explicit
构造/转换,而
push_-back
不允许。@pickypg:当然可以,如果你发现自己经常使用这种模式,那么请这样做。不过,有时候我喜欢保持简单,直到迫切需要抽象。
for (auto & f : act) { f(); }