I'm not sure about the title of the question, but basically I'm curious of how to create a visitor-like function that can operate on certain types on a collection that correctly uses type inference.
For example, a collection contains objects that inherit from a single base class (Base
). Some operations apply only to specific child classes (e.g., FooBar
inherits from Base
).
One implementation can be
template<class T, class F>
void visit(F f)
{
for (auto c : the_collection) {
if (auto t = dynamic_cast<T*>(c)) {
f(t);
}
}
}
The problem here is that invoking such function will need to specify the class type FooBar
twice:
visit<FooBar>([](FooBar* f) { f->some_method(); });
I'd like to use type inference, so I can just write visit([](FooBar* f) ...
, but can't manage to get the right template.
For example:
template<class T>
using Visitor = std::function<void(T*)>;
template<class T>
void visit(const Visitor<T>& f)
{
for (auto c : the_collection)
if (auto t = dynamic_cast<T*>(c))
f(t);
}
works with visit<FooBar>([](FooBar*) ...
but not with visit([](FooBar*) ...
.
no matching overloaded function found
void visit(const std::function<void(T *)> &)': could not deduce template argument for 'const std::function<void(T *)> &' from '{....}::<lambda_2c65d4ec74cfd95c8691dac5ede9644d>
Is it possible to define a template that can infer the types in this way or the language specification doesn't allow to do that?