I have a simple class A
, providing a variadic function template. This function uses private data from within A
, but the function itself is public. The class goes as follows:
class A {
public:
A() :
_bla("bla: ") {
}
template <class T>
void bar(const T& value) {
std::cout << _bla << value << std::endl;
}
template <class H, class... T>
void bar(const H& value, const T&... data) {
std::cout << _bla << value << std::endl;
bar(data...);
}
private:
const std::string _bla;
};
In a separate file, named foo.hpp, I have a function foo()
, that should be able to receive and use the function a.bar()
as an argument:
int main(int argc, char *argv[]) {
A a;
a.bar(1, "two", 3, 4);
foo(&a.bar);
}
I'm not very sure of where to start, but I've tried the following -- which does not work. How can I do it correctly:
template <typename... T>
inline void foo(void (bar *)(const T&...)) {
unsigned int x(0), y(0), z(0);
bar(x, y, z);
}
Bonus question: is there a way to call not only:
foo(&a.bar);
but also call foo
with a.bar
bound to some parameters, like:
foo(&(a.bar(p1, p2));
I can simply add p1
and p2
to foo
definition itself, like in:
foo(p1, p2, &a.bar);
but it would be semantically better to my purpose if I could add these parameters before.
You cannot pass the address of a function template without instantiating it, because that is treated as a whole overload set (no matter whether the template is variadic or not). You can, however, wrap it in a generic functor:
struct bar_caller
{
template<typename... Ts>
void operator () (A& a, Ts&&... args)
{
a.bar(std::forward<Ts>(args)...);
}
};
And then let your function foo()
be defined as follows:
template<typename F>
inline void foo(A& a, F f) {
unsigned int x(0), y(0), z(0);
f(a, x, y, z);
}
So your function call in main()
would become:
int main()
{
A a;
a.bar(1, "two", 3, 4);
foo(a, bar_caller());
}
Unfortunately, at the moment there is no way in C++ to easily wrap an overload set in a functor without defining a separate class - as done above for bar_caller
.
EDIT:
If you do not want to pass an A
object directly to foo()
, you can still let your bar_caller
encapsulate a reference to the A
object on which the function bar()
has to be called (just take care of object lifetime, so that you won't be making that reference dangling):
struct bar_caller
{
bar_caller(A& a_) : a(a_) { }
template<typename... Ts>
void operator () (Ts&&... args)
{
a.bar(std::forward<Ts>(args)...);
}
A& a;
};
You could then rewrite foo()
and main()
as follows:
template<typename F>
inline void foo(F f) {
unsigned int x(0), y(0), z(0);
f(x, y, z);
}
int main()
{
A a;
a.bar(1, "two", 3, 4);
foo(bar_caller(a));
}
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