我可以在C++中创建一个匿名的动态类(接口的实现)

nap*_*con 5 c++ lambda anonymous-class first-class-functions c++11

在C++中,我可以动态创建一个接口的实现(理想情况下绑定本地范围的变量.)不确定如何更好地解释它,所以我将放下我希望代码看起来像(大致):

// Given the following:

class Visitor
{
    virtual void visit(const Data& data) = 0;
}

class DataStore
{
    void visitData(Visitor& visitor) { /** Invokes visitor with each item of data. */ }
}

// Imagine one would write something like:

void inSomeFunction(DataStore& store)
{
    std::string myName = "bob";

    class MyVisitor: public Visitor
    {
    public:
        MyVisitor(const std::string& p): person(p);
        virtual void visit(const Data& data) override
        {
            std::cout << person << " is visiting " << data << std::endl;
        }
    private:
        std::string person;
    }

    MyVisitor myVisitor(myName);
    store.visitData(myVisitor);
}

// Instead of the above, I want to write instead something like:

void inSomeFunction(DataStore& store)
{
    std::string myName = "bob";

    store.visitData(
        class: public MyVisitor
        {
            virtual void visit(const Data& data) override
            {
                std::cout << myName << " is visiting " << data << std::endl;
            }
        }
    );
}
Run Code Online (Sandbox Code Playgroud)

我意识到我在这里问了两个问题 - 你能不能创建一个像这样的匿名类,你可以绑定本地范围内的变量(就像我提到的myName).但我需要两者都有用.

如果无法完成上述工作,那么在简洁性/缺乏样板文件方面,使用C++ 11 lambdas或类似方法最接近的是什么.

Bar*_*rry 10

如果你必须有一个接口,那么你应该做Kerrek建议的.

但更好的方法是改变你的界面:

class DataStore
{
    void visitData(Visitor& visitor) { 
        // bunch of calls to visitor.visit(...) ... 
    }
}
Run Code Online (Sandbox Code Playgroud)

至:

    template <class Visitor>
    void visitData(Visitor visitor) { 
        // bunch of calls to visitor(...) ... 
    }
Run Code Online (Sandbox Code Playgroud)

这将允许您简单地写:

std::string myName = "bob";
store.visit([myName](const Data& data) {
    std::cout << myName << " is visiting " << data << std::endl;
});
Run Code Online (Sandbox Code Playgroud)

这在我看来更自然.如果界面DataStore不在您的控制之下,那么这个答案完全没有实际意义.


Ker*_* SB 6

你可以用另外一个级别的间接来做到这一点:

#include <functional>
#include <utility>

class AdHocVisitor : public Visitor
{
public:
    explicit AdHocVisitor(std::function<void(const Data&)> f) : f_(std::move(f)) {}
    void visit(const Data& data) override { f_(data); }
private:
    std::function<void(const Data&)> f_;
};
Run Code Online (Sandbox Code Playgroud)

用法:

AdHocVisitor v([a, &b, this](const Data&) {});
store.visitData(v);
Run Code Online (Sandbox Code Playgroud)