Reputation: 17265
How can I boost::bind()
a template function?
I want this code (inspired by the boost::bind
bind_as_compose.cpp
example) to compile and run. Note the evaluation is different than in the bind_as_compose.cpp
example; fff()
begins running before kkk()
:
template<class F>
void fff(F fun)
{
std::cout << "fff(";
fun();
std::cout << ")";
}
void kkk()
{
std::cout << "kkk()";
}
void test()
{
fff(kkk); // "Regular" call - OK
// bind(fff,kkk)(); // Call via bind: Does not compile!!!
}
To print:
fff(kkk())
fff(kkk())
Update: Based on this answer, I got this to work:
void (&fff_ptr)(void(void)) = fff;
boost::bind(fff_ptr, kkk)();
However, this requires me to explicitly specify the instantiation types, which kinds beats the purpose...
Update 2
Ultimately, I wanted to pass the bound object as a nullary callable-type argument to another function like fff()
. In this case, what would be the explicit types?
Say I have another template function ggg()
:
template<class F>
void ggg(F fun)
{
std::cout << "ggg(";
fun();
std::cout << ")";
}
How can I use bind to get this output: fff(ggg(kkk()))
?
This does not seem to work:
boost::bind(fff<void()>, boost::bind(ggg<void()>, kkk))();
Upvotes: 0
Views: 619
Reputation: 17265
Answering myself... seems like boost::bind
is not the way to go here.
I ended up with this:
template <typename Fun>
class FFF_t
{
public:
FFF_t(Fun fun): realFun(fun) {}
void operator()() { invoke(); }
void invoke()
{
std::cout << "fff(";
realFun();
std::cout << ")";
}
private:
Fun realFun;
};
template<class Fun>
FFF_t<Fun> fff(Fun fun)
{ return FFF_t<Fun>(fun); }
This allows me to write
fff(fff(kkk))();
which gives fff(fff(kkk()))
as expected.
bind()
can still be used as the inner functor as in fff(fff(bind(some2argFun,1,2))))()
.
What I couldn't figure out was how to make the return type of invoke()
and operator()()
's dependent on the return type of Fun()
(void
in the example).
Hat-tip to @Igor R. for his comment that sent me in this direction.
Upvotes: 0
Reputation: 7119
#include <iostream>
#include <functional>
template<class F>
void fff(F fun)
{
std::cout << "fff(";
fun();
std::cout << ")" << std::endl;
}
void kkk()
{
std::cout << "kkk()";
}
int main()
{
// "Regular" call - OK
fff(kkk);
// you have to specify template parameters:
std::bind(&fff<void()>, &kkk)();
return 0;
}
output is:
zaufi@gentop /work/tests $ g++11 -o bind_test bind_test.cc
zaufi@gentop /work/tests $ ./bind_test
fff(kkk())
fff(kkk())
according your second part of the question:
boost::bind(fff, boost::bind(ggg, kkk))();
this wouldn't compile, because the argument of the outer bind
is not a void()
type!
it is actually really complex template that definitely can't be casted to void()
Upvotes: 1