[Boost.Function] detecting ignored arguments?
I have a callback-interface that can optionally process a "ServerError". If the callback looks at the error, there should be no default processing of the error. I have created a class callback that accepts two kinds of Boost.Functions: one with, one without an error object. When passing a callback function that does not look at the error, the call is ambiguous: both Boost.Functions could accept it. Is there a way to work around that problem? Can callback detect what kind of function it was passed? Some code illustrating my question: #include <boost/function.hpp> class ServerError; template<typename T> struct callback { typedef boost::function<void(T)> cb_func; cb_func callback_; typedef boost::function<void(T,const ServerError&)> cb_err_func; cb_err_func callback_err_; callback(const cb_func &cb) : callback_(cb) {} callback(const cb_err_func &cb) : callback_err_(cb) {} }; static void xxx(int) {} int main (int argc, char **argv) { // does not compile: ambiguous... callback<int> cb(&xxx); // does compile: but I'd like the compiler (or my lib) to automatically pick // the right one callback<int> cb(callback<int>::cb_func(&xxx)); return 0; } In the meantime I have found a possible workaround: If I change typedef boost::function<void(T,const ServerError&)> cb_err_func; to typedef boost::function<void(const ServerError&,T)> cb_err_func; the code does compile. Best regards and thank you for looking into this Christoph
I have a callback-interface that can optionally process a "ServerError". If the callback looks at the error, there should be no default processing of the error.
I have created a class callback that accepts two kinds of Boost.Functions: one with, one without an error object.
When passing a callback function that does not look at the error, the call is ambiguous: both Boost.Functions could accept it. Is there a way to work around that problem? Can callback detect what kind of function it was passed?
Some code illustrating my question:
#include <boost/function.hpp> class ServerError;
template<typename T> struct callback { typedef boost::function<void(T)> cb_func; cb_func callback_; typedef boost::function<void(T,const ServerError&)> cb_err_func; cb_err_func callback_err_; callback(const cb_func &cb) : callback_(cb) {} callback(const cb_err_func &cb) : callback_err_(cb) {} };
static void xxx(int) {}
int main (int argc, char **argv) { // does not compile: ambiguous... callback<int> cb(&xxx); // does compile: but I'd like the compiler (or my lib) to automatically pick // the right one callback<int> cb(callback<int>::cb_func(&xxx)); return 0; }
I haven't managed to realise why you get this specific error (maybe it's some weird MSVC bug), but Boost.Function expects a callable with the exact signature. Try the following: boost::function<void(int)> f1(xxx); boost::function<void(int, const ServerError&)> f2(xxx); and you'll see that the 2nd line does not compile.
Igor R wrote: [snip] Thank you for your reply.
I haven't managed to realise why you get this specific error (maybe it's some weird MSVC bug), but Boost.Function expects a callable with I am using gcc 4.4.1 (OpenSuSE 11.2).
the exact signature. Try the following: boost::function<void(int)> f1(xxx); boost::function<void(int, const ServerError&)> f2(xxx); and you'll see that the 2nd line does not compile. Indeed, the second line does not compile. Makes me wonder the more why the template is ambiguous: when I comment the "good" constructor out, the code is no longer ambiguous, but does not compile as well.
On Mon, Jun 25, 2012 at 4:21 AM, Christoph Duelli <duelli@melosgmbh.de>wrote: [...]
I have created a class callback that accepts two kinds of Boost.Functions: one with, one without an error object.
[...]
Some code illustrating my question:
#include <boost/function.hpp> class ServerError;
template<typename T> struct callback { typedef boost::function<void(T)> cb_func; cb_func callback_; typedef boost::function<void(T,const ServerError&)> cb_err_func; cb_err_func callback_err_; callback(const cb_func &cb) : callback_(cb) {} callback(const cb_err_func &cb) : callback_err_(cb) {} };
static void xxx(int) {}
int main (int argc, char **argv) { // does not compile: ambiguous... callback<int> cb(&xxx); // does compile: but I'd like the compiler (or my lib) to automatically pick // the right one callback<int> cb(callback<int>::cb_func(&xxx)); return 0; }
[...] I think this might due to boost::function's templated constructor being unconstrained [1]: template<typename F> functionN(F); It looks to me, then, that a void (*)( int ) is, at least superficially, convertible to boost::function< Signature > regardless of Signature (hence the ambiguity), but the body of the converting constructor will only compile if Signature and void ( int ) are compatible. Perhaps worth it to add a boost::enable_if to the functionN constructor to restrict the class of function pointers that can bind to it.
In the meantime I have found a possible workaround: If I change typedef boost::function<void(T,const ServerError&)> cb_err_func; to typedef boost::function<void(const ServerError&,T)> cb_err_func; the code does compile.
Okay, never mind, my theory above seem to run counter to this fact :( - Jeff [1] http://www.boost.org/doc/libs/1_49_0/doc/html/boost/functionN.html
participants (3)
-
Christoph Duelli
-
Igor R
-
Jeffrey Lee Hellrung, Jr.