In C++, can I create an implementation of an interface on the fly (which ideally binds local-scope variables.) Not sure how to explain it better, so I will put down what I would like the code to look like (roughly):
// 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;
}
}
);
}
I realise that I'm asking 2 questions here - can you create an anonymouse class like this, and can you bind variables from the local scope (like I've referred to myName). But I need both for it to be useful.
If the above can't be done, what's the closest one can get to using say C++11 lambdas or similar, in terms of conciseness / lack of boilerplate.
If you have to have an interface, then you should do what Kerrek suggested.
But even better would be to change your interface from:
class DataStore
{
void visitData(Visitor& visitor) {
// bunch of calls to visitor.visit(...) ...
}
}
to:
template <class Visitor>
void visitData(Visitor visitor) {
// bunch of calls to visitor(...) ...
}
This would allow you to simply write:
std::string myName = "bob";
store.visit([myName](const Data& data) {
std::cout << myName << " is visiting " << data << std::endl;
});
which is far more natural in my opinion. If the interface of DataStore
is outside of your control, then this answer is totally moot.
You can do it with one more level of indirection:
#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_;
};
Usage:
AdHocVisitor v([a, &b, this](const Data&) {});
store.visitData(v);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With