In C++11 or above, Is there a way to implement a single-method pure virtual C++ interface by lambda?

You can create a wrapper, e.g.:

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)};
}

And then to create the task:

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

Note that you still need to have a wrapper and a makeXXX function for each one of your interface. With C++17 and above, you can get rid of the makeXXX function by using class template argument deduction. Getting rid of the wrapper is not possible but you might be able to reduce the boilerplate code by encapsulating some stuff in macros.


Here is an example macro (not perfect) that could be used to reduce the boilerplate code:

#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)}; }

And then:

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);

Isn't it what you are looking for?

std::thread t(
  [](){
    std::cout << "thread\n"; // Here is the code run by the thread...
  }
);
std::cout << "main\n";
t.join();

Old Virtual interface style:

struct MyInterface {
    virtual Type action(argList)  = 0;
};

class MyClassThatUsesInterface
{
    MyInterface&   interface;
    public:
        MyClassThatUsesInterface(MyInterface& ref)
            : interface(ref)
        {}
        Type doStuff(argList)
        {
             return interface.action(argList);
        }
};
...
MyInterfaceImplementation injectedInterface;
MyClassThatUsesInterface  worker(injectedInterface);
...
worker.doStuff(someStuff);

More Modern style:
Or Duck Typing Style:

// No need for an explicit interface definition.
// Any function that will work can be used
// Let the compiler decide if the used function (functor/lambda) works.

template<typename F>
class MyClassThatUsesLambda
{
    F   interface;
    public:
        MyClassThatUsesLambda(F&& ref)
            : interface(std::move(ref))
        {}
        Type doStuff(argList)
        {
             return interface(argList);
             // Will compile if the type F supports function like operations.
             // This means a:
             //   * function pointer.
             //   * std::function
             //   * A type the overloads operator()
             //   * Lambda
        }
};
template<typename F>
MyClassThatUsesLambda<F> make_MyClassThatUsesLambda(F&& f) {return MyClassThatUsesLambda<F>(std::move(f));}
...
auto  worker = make_MyClassThatUsesLambda([](argList){/* Some Stuff*/});
...
worker.doStuff(someStuff);

Looking at your example (Which is obviously not C++ by the way)

// Added C++ required virtuals etc:
// Some basic memory management (not checked).
class SimpleTask
{
    public:
        virtual void run() = 0;
};
// Guessed at this object.
class Thread
{
    std::string                    name;
    std::unique_ptr<SimpleTask>    task
    public:
        Thread(std::string const& name, std::unique_ptr<SimpleTask>&& task)
            : name(name)
            , task(std:move(task))
        {}
        void start() {
            task.run();
        }
};
void myFunction()
{
    class MySimpleTask: public SimpleTask
    {
        public:
            virtual void run() override
            {
                //Do something for this task
                ...
                // Destroying this is an exceptionally bad idea.
                // Let the owner destroy it.
                // I made the task hold it as an std::unique_ptr
                // To solve this.    
                // delete this;    //Finally, destroy the instance
            }
    };
    ...
    Thread myThread("MyTestingThread", std::make_unique<MySimpleTask>());
    myThread.start();
    ...
}

Now lets re-write using duck typing:

template<typename F>
class Thread
{
    std::string                    name;
    F                              task
    public:
        Thread(std::string const& name, F&& task)
            : name(name)
            , task(std:move(task))
        {}
        void start() {
            task();
        }
};
template<typename F>
Thread<F> make_Thread(std::string const& name, F&& f) {return Thread<F>(name, std::move(f));}
void myFunction()
{ 
    ...
    auto  myThread = make_Thread("MyTestingThread", [](argList){/* Do something for this task */});
    myThread.start();
    ...
}

Tags:

C++

Lambda

C++11