c++ - 在C++11或更高版本中,有没有办法通过lambda实现单方法纯虚C++接口(interface)?

标签 c++ c++11 lambda

我有一个用 C++ 98 编写的大型 C++ 库,它大量使用 C++ 接口(interface)(准确地说,只有纯虚函数的 C++ 类)来处理事件。现在看到我的代码是由 C++11/14 编译器编译的,我在想是否可以通过使用 C++11 lambda 替换接口(interface)实现来减少样板代码。

在我的库中,有一些 C++ 接口(interface)只有一个方法,例如,我们用来定义一个简单任务的以下接口(interface):

class SimpleTask
{
public:
    virtual void run() = NULL;
};

我的意图是使用 C++ lambda 来替换旧的单一方法接口(interface)实现代码,如下所示:

void myFunction()
{
    ...

    class MySimpleTask : SimpleTask //An inline class to implement the iterface
    {
    public:
        void run() 
        {
            //Do somthing for this task
            ...    
            delete this;    //Finally, destroy the instance
        }
    };
    MySimpleTask * myThreadTask = new MySimpleTask();
    Thread myThread(L"MyTestingThread", myThreadTask);
    myThread.start();

    ...
}

在 Java 8 中,we can use Java lambda to implement a single-method interface编写代码比使用匿名类更简洁。我在 C++11 中做了一些研究,发现没有类似的东西。

由于我的库的事件处理代码是以面向对象的模式设计的,而不是以函数式编码风格设计的,有没有办法使用 lambda 来帮助减少那些单一方法接口(interface)实现代码?

最佳答案

您可以创建一个包装器,例如:

class SimpleTask {
public:
    virtual void run() = 0;
};

// This class wraps a lambda (or any callable) and implement the run()
// method by simply calling the callable.
template <class T>
class LambdaSimpleTask: public SimpleTask {
    T t;

public:
    LambdaSimpleTask(T t) : t(std::move(t)) { }

    virtual void run() {
        t();
    }
};


template <class T>
auto makeSimpleTask(T &&t) {
    // I am returning a dynamically allocated object following your example,
    // but I would rather return a statically allocated one.
    return new LambdaSimpleTask<std::decay_t<T>>{std::forward<T>(t)};
}

然后创建任务:

auto task = makeSimpleTask([]() { });
Thread myThread(L"MyTestingThread", task);

请注意,您仍然需要为每个界面设置一个包装器和一个makeXXX 函数。使用 C++17 及更高版本,您可以通过使用类模板参数推导来摆脱 makeXXX 函数。摆脱包装器是不可能的,但您可以通过在宏中封装一些东西来减少样板代码。


这是一个示例宏(不完美),可用于减少样板代码:

#define WRAPPER_FOR(C, M, ...)                       \
    template <class T>                               \
    class Lambda##C: public C {                      \
        T t;                                         \
    public:                                          \
        Lambda##C(T t) : t(std::move(t)) { }         \
        virtual M { return t(__VA_ARGS__); }         \
    };                                               \
    template <class T> auto make##C(T &&t) {         \
        return Lambda##C<std::decay_t<T>>{std::forward<T>(t)}; }

然后:

class SimpleTask {
public:
    virtual void run() = 0;
};

class ComplexTask {
public:
    virtual int run(int, double) = 0;
};

WRAPPER_FOR(SimpleTask, void run());
WRAPPER_FOR(ComplexTask, int run(int a, double b), a, b);

关于c++ - 在C++11或更高版本中,有没有办法通过lambda实现单方法纯虚C++接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56259644/

相关文章:

Qt:在 lamdas 中发出信号好还是不好的风格(并且会引起问题)

c++ - 当 `sleep_until()` 指定过去的时间点时,行为是否明确?

c++ - 通过引用 C++ 初始化指针数组

c# - 如何动态创建以下 LINQ 表达式?

c++ - C++ 中的性能比较(普通函数调用与 for_each+mem_fun 与 lambda 表达式)

c++ - 如何摆脱 Xcode 4 中的 "In class initializer for static data member ... is a C++0x extension"警告

c++ - 优雅地尝试以特定方式执行各种功能

c++ - UNIX : One running a ruby server and other C++ client 中 2 个进程之间通信的最佳方式

c++ - Effective Modern C++ 书中 ThreadRAII 的实现是否正确?

c++ - 为什么在调用不明确的ctor时没有编译时错误?