简体   繁体   English

C#通用委托的C ++等效语法以及lambdas的用法

[英]C++ equivalent syntax for a C# generic delegate, and usage with lambdas

In C# I can do this: 在C#中,我可以这样做:

delegate void myFunctionDelegate<T>(T arg);

In C++, I understand that I need to use an alias to a template for a function pointer, but the syntax is so bizaare that all of the examples I find just confuse me more. 在C ++中,我了解到我需要为函数指针使用模板的别名,但是语法是如此古怪,以至于我发现的所有示例都使我更加困惑。

The following is wrong; 以下是错误的; how can I correct it? 我该如何纠正?

template<typename T>
using myFunctionDelegate = void (*)(T arg);

I want to use it like so: 我想这样使用它:

template<class T> class Foo
{
    ...
    void someOtherFunction(myFunctionDelegate callback)
    {
        ...
        callback(someValue);
    }
}

and then: 接着:

myClassInstance.someOtherFunction([&](T arg) {
    // do something with the callback argument
});

What you have almost works syntactically; 您所拥有的几乎都在语法上起作用; the use of myFunctionDelegate simply needs a type argument: 使用myFunctionDelegate只需一个类型参数:

void someOtherFunction(myFunctionDelegate<T> callback)
                                         ^^^

And the alias parameter names are optional if you aren't getting any particular benefit from them: 如果您没有从别名参数中获得任何特殊的好处,则别名参数名称是可选的:

template<typename T>
using myFunctionDelegate = void(*)(T);

However, there is a larger problem: function pointers don't handle state. 但是,存在一个更大的问题:函数指针不处理状态。 The lambda used in your sample call uses state by the capturing it does. 样本调用中使用的lambda通过捕获状态来使用状态。 Thus, a capturing lambda cannot be converted to a function pointer. 因此,捕获的lambda无法转换为函数指针。 When it's so handy to pass in such a lambda, function arguments should support that. 当如此方便地传递这样的lambda时,函数参数应该支持它。

There are two common ways of doing so. 有两种常用的方法。 The first is to forget about forcing a specific return and parameter type. 首先是忘记强制使用特定的返回值和参数类型。 Instead, let the caller pass any object (lambda, function pointer, functor, the result of std::bind ) that can be called the way your function calls it: 相反,让调用者传递可以调用函数的任何对象(lambda,函数指针,函子, std::bind的结果):

template<typename Callable>
void someOtherFunction(Callable callback) {
    ...
    callback(someValue);
}

If the call doesn't work, the code will fail to compile 1 (with an error that unfortunately isn't too helpful, but the future Concepts additions can easily help there). 如果调用不起作用,则代码将无法编译1 (不幸的是,该错误不太有用,但将来在Concepts中添加的内容很容易在其中提供帮助)。

On the other hand, you might want to explicitly specify the function type. 另一方面,您可能要显式指定函数类型。 C++ has a general-purpose type to store any callable object (see the above list). C ++具有通用类型来存储任何可调用对象(请参见上面的列表)。 That type is std::function . 该类型是std::function It's a bit more heavyweight than a simple template parameter, but useful when you need it. 它比简单的模板参数要重一些,但是在需要时很有用。

template<typename T>
using myFunctionDelegate = std::function<void(T)>;

void someOtherFunction(const myFunctionDelegate<T> &callback) {...}

[1]: This isn't always true (see SFINAE), but it probably will be as far as you're concerned. [1]:这并不总是正确的(请参阅SFINAE),但就您所关心的而言,可能是正确的。

std::function<void(T)> myFunctionDelegate is the (very) rough equivalent of delegate void myFunctionDelegate<T>(T arg) std::function<void(T)> myFunctionDelegatedelegate void myFunctionDelegate<T>(T arg)的(非常)大致等效delegate void myFunctionDelegate<T>(T arg)

std::function<void(T)> follows value semantics (it behaves more like an int than a C# object reference) which makes things different. std::function<void(T)>遵循值语义(使行为与C#对象引用更像是int ),这使情况有所不同。

A lambda closure ( [](T t){/*code*/} ) whose lifetime (or copies of it) outlives the local scope should not use & based capture. Lambda闭包( [](T t){/*code*/} )的生存期(或它的副本)超过本地范围的生存期,不应使用&基于捕获。 Instead use = based capture (which may require extra work). 而是使用基于=的捕获(可能需要额外的工作)。 If the code you are calling does not store a copy of the delegate beyond the lifetime of the call, [&] is optimal. 如果您正在调用的代码在调用的生命周期内未存储委托的副本,则[&]是最佳选择。 In C++ the lifetime of data is something you need concern yourself with. 在C ++中,您需要关注数据的生命周期。

This is not intended as a full tutorial on how lambdas and std::function work, but just to point you in the right direction. 这并不是作为有关lambdas和std::function如何工作的完整教程,而只是为您指明正确的方向。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM