[function,bind] Templated function<> function

Ok, the subject-line might be a bit confusing. :-) I have the following template function: template<class T> bool is(const string& str); Its implementation is not important. It checks if a string can be converted to type T by std::stringstream. I also have the following function: template <class T> function<bool (T)> neg(function<bool (T)> func) { return !bind(func, _1); } Which I use in the following way: BOOST_CHECK_PREDICATE( neg(is<int>), ("text") ); But the compiler (GCC 4.1.2) complains: error: no matching function for call to 'neg(<unresolved overloaded function type>)' What's the problem. And, also, what's the solution? :-) Thanks in advance! -- Michiel Helvensteijn

AMDG Michiel Helvensteijn wrote:
Ok, the subject-line might be a bit confusing. :-)
I have the following template function:
template<class T> bool is(const string& str);
Its implementation is not important. It checks if a string can be converted to type T by std::stringstream. I also have the following function:
template <class T> function<bool (T)> neg(function<bool (T)> func) { return !bind(func, _1); }
Which I use in the following way:
BOOST_CHECK_PREDICATE( neg(is<int>), ("text") );
But the compiler (GCC 4.1.2) complains:
error: no matching function for call to 'neg(<unresolved overloaded function type>)'
What's the problem. And, also, what's the solution? :-)
Internal to the compiler, the type of is<int> is a special type used to flag overloads. (unresolved overloaded function type). The problem is that you are passing this special type to a function template (the boost::function constructor) which does not provide enough information to resolve the overloading. The solution is to add a cast: static_cast<bool(*)(const std::string&)(&is<int>)> In Christ, Steven Watanabe

Steven Watanabe wrote:
But the compiler (GCC 4.1.2) complains:
error: no matching function for call to 'neg(<unresolved overloaded function type>)'
What's the problem. And, also, what's the solution? :-)
Internal to the compiler, the type of is<int> is a special type used to flag overloads. (unresolved overloaded function type). The problem is that you are passing this special type to a function template (the boost::function constructor) which does not provide enough information to resolve the overloading.
Maybe I misunderstand your explanation. But I'm not sure if is<int> has anything to do with the problem. As a test I tried the following: bool foo(int a) { return a == 1; } ... BOOST_CHECK_PREDICATE( neg(foo), (2) ); Which gives a similar (though less unresolved) error-message: error: no matching function for call to 'neg(bool (&)(int))'
The solution is to add a cast: static_cast<bool(*)(const std::string&)(&is<int>)>
Hm. That's not exactly pretty. I'd rather use boost::bind itself on the call site. I was hoping to be able to fix something in the definition of neg instead. -- Michiel Helvensteijn

AMDG Michiel Helvensteijn wrote:
BOOST_CHECK_PREDICATE( neg(foo), (2) );
Which gives a similar (though less unresolved) error-message:
error: no matching function for call to 'neg(bool (&)(int))'
neg(&foo) might work better.
The solution is to add a cast: static_cast<bool(*)(const std::string&)(&is<int>)>
Hm. That's not exactly pretty. I'd rather use boost::bind itself on the call site. I was hoping to be able to fix something in the definition of neg instead.
Does it work if you make the argument to neg bool (*f)(const std::string&)? In Christ, Steven Watanabe

Steven Watanabe wrote:
Which gives a similar (though less unresolved) error-message:
error: no matching function for call to 'neg(bool (&)(int))'
neg(&foo) might work better.
I tried that too. The error is: error: no matching function for call to 'neg(bool (*)(int))'
Hm. That's not exactly pretty. I'd rather use boost::bind itself on the call site. I was hoping to be able to fix something in the definition of neg instead.
Does it work if you make the argument to neg bool (*f)(const std::string&)?
Yes. Both: function<bool (string)> neg(bool(*func)(const string&)) and function<bool (string)> neg(function<bool (string)> func) work as expected. But you understand why I'd like the templated version to work. I have other predicates to test. -- Michiel Helvensteijn

AMDG Michiel Helvensteijn wrote:
But you understand why I'd like the templated version to work. I have other predicates to test
Ok. The compiler can't deduce T in template <class T> function<bool (T)> neg(function<bool (T)> func); unless the argument is already a boost::function. No implicit conversions allowed. template<class F> struct not_t { typedef bool result_type; template<class T> bool operator()(const T& t) { return(!f(t)); } F f; }; template<class F> not_t<F> neg(F f) { not_t<F> result = { f }; return(result); } In Christ, Steven Watanabe

Steven Watanabe wrote:
But you understand why I'd like the templated version to work. I have other predicates to test
Ok. The compiler can't deduce T in
template <class T> function<bool (T)> neg(function<bool (T)> func);
unless the argument is already a boost::function. No implicit conversions allowed.
I suspected it was too much to ask for. But I didn't know any alternative.
template<class F> struct not_t { typedef bool result_type; template<class T> bool operator()(const T& t) { return(!f(t)); } F f; };
template<class F> not_t<F> neg(F f) { not_t<F> result = { f }; return(result); }
This works as expected! So it's a function object, huh. I haven't used those before. I changed your solution in two small ways: * I removed the unused typedef. * I added some overloads of operator() to handle multiple parameters. This is a useful feature to have. Thanks for your help! -- Michiel Helvensteijn
participants (2)
-
Michiel Helvensteijn
-
Steven Watanabe