How to detect if f() returns void or not?

I would like to detect if the return type of a function is void or not within C++03 standard? I need that to implement new type traits to detect if types can be compared and to detect for example operator< returning void. The following code compiles only with c++0x standard and keyword decltype but not with c++03 standard and BOOST_TYPEOF. Frédéric #include <iostream> #include <boost/type_traits/is_void.hpp> #include <boost/typeof/typeof.hpp> void returns_void(); int returns_int(); int main() { std::cout<<std::boolalpha; // std::cout<<boost::is_void< BOOST_TYPEOF(returns_void()) >::value<<'\n'; // std::cout<<boost::is_void< BOOST_TYPEOF(returns_int()) >::value<<'\n'; std::cout<<boost::is_void< decltype(returns_void()) >::value<<'\n'; std::cout<<boost::is_void< decltype(returns_int()) >::value<<'\n'; return 0; }

Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard?
Hi, Did you look at Boost.FunctionTypes ? http://www.boost.org/doc/libs/1_41_0/libs/function_types/doc/html/boost_func... -- Maxime

Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? I need that to implement new type traits to detect if types can be compared and to detect for example operator< returning void. The following code compiles only with c++0x standard and keyword decltype but not with c++03 standard and BOOST_TYPEOF. Frédéric
What about using function_traits::return_type ? -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

Did you look at Boost.FunctionTypes ? What about using function_traits::return_type ?
The problem is that I do not even know the function the return type I want to know because it is the result of a<b. If operator<(A,B) does not exist there may be another operator< that is still fine with appropriate convertions. So what I really want is the type of an expression, not of a function, the expression being a<b. Frédéric

Frédéric Bron wrote:
The problem is that I do not even know the function the return type I want to know because it is the result of a<b. If operator<(A,B) does not exist there may be another operator< that is still fine with appropriate convertions. So what I really want is the type of an expression, not of a function, the expression being a<b.
I fear you must resort to BOOST_TYPEOF. -- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

joel falcou wrote:
I fear you must resort to BOOST_TYPEOF.
The problem is that you cannot use BOOST_TYPEOF with void expressions it seems. Here is what his code expands in : -------------------------------------------------------------------- namespace boost { namespace type_of { template<typename T> typename enable_if<is_function<T>, T&>::type ensure_obj(T&); template<typename T> typename disable_if<is_function<T>, T&>::type ensure_obj(const T&); }} void returns_void(); int returns_int(); int main() { std::cout<<std::boolalpha; std::cout<<boost::is_void< __typeof__(boost::type_of::ensure_obj(void))
::value<<'\n';
return 0; } -------------------------------------------------------------------- The ensure_obj expansion fails because T cannot be void. -- Maxime

Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip>
I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr... HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not. Frédéric

Hi,
I would like to detect if the return type of a function is void or not within C++03 standard?
You can specialize on function type (provided that the arguments are known). template <typename T> struct check_void : boost::false_type {}; template <> struct check_void<void (*)()> : boost::true_type {}; void returns_void() {} int returns_int() { return 0; } template <typename F> void test_type(F function) { std::cout << typeid(F).name() << (check_void<F>::value ? " true" : " false") << std::endl; } int test_main(int, char* []) { test_type(returns_void); test_type(returns_int); ...
I need that to implement new type traits to detect if types can be compared and to detect for example operator< returning void.
I don't know if you can use it like this on an operator< returning void. Regards, Barend

Frédéric Bron wrote:
I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not.
I find your lack of faith disturbing. #include <boost/static_assert.hpp> typedef char yes_type; typedef char (&no_type)[2]; struct void_return { template<typename T> friend int operator,(T const &, void_return); }; no_type check_is_void_return(int); yes_type check_is_void_return(void_return); // check to see if the expression fun(x,y) is void template<typename Fun, typename X, typename Y> struct returns_void { static Fun &fun; static X &x; static Y &y; static bool const value = sizeof(yes_type) == sizeof(fun(x,y),void_return()); }; int main() { BOOST_STATIC_ASSERT((returns_void<void(int,int),int,int>::value == 1)); BOOST_STATIC_ASSERT((returns_void<int(int,int),int,int>::value == 0)); } HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Frédéric Bron wrote:
Eric Niebler wrote:
I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not.
I find your lack of faith disturbing. <snip>
Corrected version... #include <boost/static_assert.hpp> typedef char yes_type; typedef char (&no_type)[2]; struct void_return { template<typename T> friend int operator,(T const &, void_return); }; no_type check_is_void_return(int); yes_type check_is_void_return(void_return); // check to see if the expression fun(x,y) is void template<typename Fun, typename X, typename Y> struct returns_void { static Fun &fun; static X &x; static Y &y; static bool const value = sizeof(yes_type) == sizeof(check_is_void_return((fun(x,y),void_return()))); }; int main() { BOOST_STATIC_ASSERT((returns_void<void(int,int),int,int>::value == 1)); BOOST_STATIC_ASSERT((returns_void<int(int,int),int,int>::value == 0)); } -- Eric Niebler BoostPro Computing http://www.boostpro.com

This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not.
I find your lack of faith disturbing.
I am very sorry for that, I did not want to hurt you; I was too rude. This just shows how far I am from your practice of C++ because the fact that I understood the operator, trick did not make me think of how to use it to perform what I wanted. I have now read carrefully your proposed code and it works! I am now able ot make the has_operator_xxxx traits work for any return type. So thank you very much and many kudos for your kind help. Frédéric

Frédéric Bron wrote:
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not. I find your lack of faith disturbing.
I am very sorry for that, I did not want to hurt you; I was too rude.
Oh, no worries! You missed the Star Wars reference. I was making a joke, not actually upset. :-)
This just shows how far I am from your practice of C++ because the fact that I understood the operator, trick did not make me think of how to use it to perform what I wanted. I have now read carrefully your proposed code and it works! I am now able ot make the has_operator_xxxx traits work for any return type. So thank you very much and many kudos for your kind help.
Excellent. Glad to be of service. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Dec 13, 2009, at 9:10 PM, Eric Niebler wrote:
Frédéric Bron wrote:
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not. I find your lack of faith disturbing. I am very sorry for that, I did not want to hurt you; I was too rude.
Oh, no worries! You missed the Star Wars reference. I was making a joke, not actually upset. :-)
According to a recent survey, the ratio of Trekkies to Star War fans among geeks is close to 10. /David

On Sun, Dec 13, 2009 at 1:40 PM, David Bergman <David.Bergman@bergmangupta.com> wrote:
On Dec 13, 2009, at 9:10 PM, Eric Niebler wrote:
Frédéric Bron wrote:
This does not check for return type but just ignores it with the operator, trick. In the end, you do not know if fun(a,b) return void or not. I find your lack of faith disturbing. I am very sorry for that, I did not want to hurt you; I was too rude.
Oh, no worries! You missed the Star Wars reference. I was making a joke, not actually upset. :-)
According to a recent survey, the ratio of Trekkies to Star War fans among geeks is close to 10.
<offtopic> I would not doubt that, I am more into the technical side rather then the magical side of things. :) Star Trek TNG, Babylon 5, etc... Not big on Star Wars...

David Bergman wrote:
According to a recent survey, the ratio of Trekkies to <snip>
Let's keep it on-topic, folks. Thanks. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
#include <boost/static_assert.hpp>
typedef char yes_type; typedef char (&no_type)[2];
struct void_return { template<typename T> friend int operator,(T const &, void_return); };
no_type check_is_void_return(int); yes_type check_is_void_return(void_return);
// check to see if the expression fun(x,y) is void template<typename Fun, typename X, typename Y> struct returns_void { static Fun &fun; static X &x; static Y &y; static bool const value = sizeof(yes_type) == sizeof(check_is_void_return((fun(x,y),void_return()))); };
int main() { BOOST_STATIC_ASSERT((returns_void<void(int,int),int,int>::value == 1)); BOOST_STATIC_ASSERT((returns_void<int(int,int),int,int>::value == 0)); }
That's a nice trick. It would be good to see this, and Joel's stuff (from the vault), put out as an introspection library. FWIW, MSVC71 coughs unless the operator, is given an implementation, i.e. struct void_return { template<typename T> friend int operator,(T const &, void_return) {return 0;} }; [shrug]

Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip>
I solved this problem once while writing a different trait and documented it here:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.

On Mon, Dec 14, 2009 at 6:40 PM, Edward Diener <eldiener@tropicsoft.com> wrote:
Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard?
<snip>
I solved this problem once while writing a different trait and documented it here:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.
Out of curiosity, but doesn't Boost.Function_Types give information about all this, including return type?

OvermindDL1 wrote:
On Mon, Dec 14, 2009 at 6:40 PM, Edward Diener <eldiener@tropicsoft.com> wrote:
Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip>
I solved this problem once while writing a different trait and documented it here:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr... It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.
Out of curiosity, but doesn't Boost.Function_Types give information about all this, including return type?
I believe the OP's question was "Can function X be invoked with a name and certain parameters and, if so, give me its return type", not "Give me the return type of known type function X". The latter, as you say, can be found out through Function_Types.

On Dec 14, 2009, at 8:40 PM, Edward Diener wrote:
Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip> I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.
We had a short discussion of the limitations of that technique here: http://cpp-next.com/archive/2009/10/this-week-in-boost/comment-page-1/#comme... -- David Abrahams BoostPro Computing http://boostpro.com

David Abrahams wrote:
On Dec 14, 2009, at 8:40 PM, Edward Diener wrote:
Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip> I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr... It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.
We had a short discussion of the limitations of that technique here: http://cpp-next.com/archive/2009/10/this-week-in-boost/comment-page-1/#comme...
I don't understand from your link what those limitations are, although it appears it revolves around the comma operator technique used by Eric Niebler in his example.

Edward Diener wrote:
David Abrahams wrote:
On Dec 14, 2009, at 8:40 PM, Edward Diener wrote:
Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip> I solved this problem once while writing a different trait and documented it here: http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
It's extremely clever, as others have noted, but I am wondering if there is any website, or possibly newsgroup, devoted to advanced TMP techniques such as yours.
We had a short discussion of the limitations of that technique here: http://cpp-next.com/archive/2009/10/this-week-in-boost/comment-page-1/#comme...
I don't understand from your link what those limitations are, although it appears it revolves around the comma operator technique used by Eric Niebler in his example.
I think the point is that if the expression returns a type that has itself overloaded the comma operator, then that overload may get selected, trowing the whole thing off-track. (I'm sure someone will correct me if I've read it too quickly and missed the point.) Anyway, that's worth noting, but hardly seems likely to occur in practice. -- Eric Niebler BoostPro Computing http://www.boostpro.com

I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited in October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know? Patrick

Patrick Horgan a écrit :
I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited in October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know?
They're guidelines if you want compatibility with MSVC6 and that kind of old compiler. My understanding is that it's not mandatory to follow them, and it would be expected that all libraries that use fairly advanced template meta-programming do not.

2009/12/15 Mathias Gaunard <mathias.gaunard@ens-lyon.org>:
Patrick Horgan a écrit :
I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited in October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know?
They're guidelines if you want compatibility with MSVC6 and that kind of old compiler.
My understanding is that it's not mandatory to follow them, and it would be expected that all libraries that use fairly advanced template meta-programming do not.
I think MPL actually makes it quite easy to follow a lot of those guidelines. I don't think we should get rid of information about older compilers, but it could be moved to a less prominent place since it isn't relevant for many new boost developers. I actually accidentally removed the old Visual C++ and Borland development info when we moved to the new site, and I've been wondering if it's worth restoring them somewhere. There hasn't been any demand though. There's a lot of work on the wiki toward establishing new guidelines, at some point someone (i.e. not me, I'm afraid) is going to have to take charge of combining them with the existing guidelines. It might even be worth moving much of the development information over to the wiki, which would let the main website focus on users. Daniel

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Daniel James Sent: Tuesday, December 15, 2009 10:51 PM To: boost@lists.boost.org Subject: Re: [boost] Do the Coding Guidelines for Integral Constant Expressions need updating?
2009/12/15 Mathias Gaunard <mathias.gaunard@ens-lyon.org>:
Patrick Horgan a écrit :
I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited
in
October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know?
There's a lot of work on the wiki toward establishing new guidelines, at some point someone (i.e. not me, I'm afraid) is going to have to take charge of combining them with the existing guidelines. It might even be worth moving much of the development information over to the wiki, which would let the main website focus on users.
A lot of code has flowed under the bridge since 2007 ;-) I would favour keeping this developers info on the wiki to make it easier to keep it up to date. (And replace the document by a link to the wiki). Paul --- Paul A. Bristow Prizet Farmhouse Kendal, UK LA8 8AB +44 1539 561830, mobile +44 7714330204 pbristow@hetp.u-net.com

Mathias Gaunard wrote:
Patrick Horgan a écrit :
I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited in October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know?
They're guidelines if you want compatibility with MSVC6 and that kind of old compiler.
My understanding is that it's not mandatory to follow them, and it would be expected that all libraries that use fairly advanced template meta-programming do not. au contraire, the doc itself says,
Coding Guidelines The following guidelines are declared in no particular order (in other words you need to obey all of them - sorry!) implying, (well actually stating) that you have to follow all of them. Patrick

AMDG Patrick Horgan wrote:
Mathias Gaunard wrote:
Patrick Horgan a écrit :
I was reading the Integral Constant Expressions doc (http://www.boost.org/development/int_const_guidelines.html), last edited in October 2007, and am guessing that some of the warnings are out of date with newer versions of some of the compilers available. Does anyone know?
They're guidelines if you want compatibility with MSVC6 and that kind of old compiler.
My understanding is that it's not mandatory to follow them, and it would be expected that all libraries that use fairly advanced template meta-programming do not. au contraire, the doc itself says,
Coding Guidelines The following guidelines are declared in no particular order (in other words you need to obey all of them - sorry!)
implying, (well actually stating) that you have to follow all of them.
In practice these guidelines are (mostly) ignored these days. In Christ, Steven Watanabe P.S. Please don't reply to an existing thread when starting a new topic.

Eric Niebler wrote:
Frédéric Bron wrote:
I would like to detect if the return type of a function is void or not within C++03 standard? <snip>
I solved this problem once while writing a different trait and documented it here:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
I gotta admit, this thing is amazing. I actually needed to implement a way to tell whether a type is an io manipulator (basically telling if calling T(ostream) is a well-formed expression), and was at a loss. I was about to post a question on comp.lang.c++ but suddenly came across this thread and your solution fit like hand in glove. I do have a question though. In your "fununwrap2" class you define the typedef as typedef private_type const &(*pointer_to_function) (dont_care, dont_care); and dont_care constructor has ellipsis instead of an argument list. Why use dont_care at all? Why not define the pointer_to_function type as: typedef private_type (*pointer_to_function) (...); It seems to be working just as good. Or am I missing something? Thanks, Andy.

Andy Venikov wrote:
Eric Niebler wrote:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
I gotta admit, this thing is amazing. I actually needed to implement a way to tell whether a type is an io manipulator (basically telling if calling T(ostream) is a well-formed expression), and was at a loss. I was about to post a question on comp.lang.c++ but suddenly came across this thread and your solution fit like hand in glove.
Great. Maybe this technique deserves to be more widely known.
I do have a question though. In your "fununwrap2" class you define the typedef as
typedef private_type const &(*pointer_to_function) (dont_care, dont_care);
and dont_care constructor has ellipsis instead of an argument list.
Why use dont_care at all? Why not define the pointer_to_function type as:
typedef private_type (*pointer_to_function) (...);
It seems to be working just as good. Or am I missing something?
I think it's me that missing something. The goal is to come up with the worst possible conversion sequence so that our overload gets picked only if there really is no other option. My thought was that using dont_care makes the conversion sequence longer because not only does it involve an ellipsis conversion, but it also involves a user-defined conversion (to dont_care). But to my surprise, that seems not to be the case. Consider this: struct dont_care {dont_care(...) {}}; char fun(dont_care) { return 0; } int fun(...) { return 0; } int main() { fun(1); typedef char assert_[1==sizeof(fun(1))]; } For some reason, the overload that involves both an ellipsis conversion *and* a user-defined conversion is actually preferred over the one that involves just an ellipsis conversion. I don't understand that, but it wouldn't be the first time that I was baffled by the C++ overloading rules. Sometimes I think I'll never really know C++. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
Andy Venikov wrote:
Eric Niebler wrote:
http://www.boost.org/doc/libs/1_41_0/doc/html/proto/appendices.html#boost_pr...
I gotta admit, this thing is amazing. I actually needed to implement a way to tell whether a type is an io manipulator (basically telling if calling T(ostream) is a well-formed expression), and was at a loss. I was about to post a question on comp.lang.c++ but suddenly came across this thread and your solution fit like hand in glove.
Great. Maybe this technique deserves to be more widely known.
I do have a question though. In your "fununwrap2" class you define the typedef as
typedef private_type const &(*pointer_to_function) (dont_care, dont_care);
and dont_care constructor has ellipsis instead of an argument list.
Why use dont_care at all? Why not define the pointer_to_function type as:
typedef private_type (*pointer_to_function) (...);
It seems to be working just as good. Or am I missing something?
I think it's me that missing something. The goal is to come up with the worst possible conversion sequence so that our overload gets picked only if there really is no other option. My thought was that using dont_care makes the conversion sequence longer because not only does it involve an ellipsis conversion, but it also involves a user-defined conversion (to dont_care). But to my surprise, that seems not to be the case.
Consider this:
struct dont_care {dont_care(...) {}};
char fun(dont_care) { return 0; } int fun(...) { return 0; }
int main() { fun(1); typedef char assert_[1==sizeof(fun(1))]; }
For some reason, the overload that involves both an ellipsis conversion *and* a user-defined conversion is actually preferred over the one that involves just an ellipsis conversion. I don't understand that, but it wouldn't be the first time that I was baffled by the C++ overloading rules.
Sometimes I think I'll never really know C++.
Is it just me or are the overload resolution rules in the standard are phrased in language really difficult to understand? I've been trying to find the answer to the ellipsis thing and, by my word, I can't understand what the rules say even after reading them several times. Anyway, Eric, I had a question regarding your technique. It looks like the technique is not going to work with functors that have templated operator() In this case the template will happily eat arguments of any type, even the ones that it's not supposed to be called with. The error will not be detected during instantiation of can_be_called<> but when the functor is actually called. So, for example, template <typename Fun, typename Arg1, typename Arg2> bool CanBeCalled(Fun const &, Arg1 const &, Arg2 const &) { return can_be_called<Fun, Arg1, Arg2>::result; } CanBeCalled(bind(main, _1, _2), string(), complex()); Will produce "true". But this: bind(main, _1, _2)(string(), complex()); Will generate a compile-time error. Do you have any other tricks up your sleeve to solve it? Thanks, Andy.

On 12/18/2009 9:16 AM, Andy Venikov wrote:
Eric Niebler wrote:
For some reason, the overload that involves both an ellipsis conversion *and* a user-defined conversion is actually preferred over the one that involves just an ellipsis conversion. I don't understand that, but it wouldn't be the first time that I was baffled by the C++ overloading rules.
Sometimes I think I'll never really know C++.
Is it just me or are the overload resolution rules in the standard are phrased in language really difficult to understand? I've been trying to find the answer to the ellipsis thing and, by my word, I can't understand what the rules say even after reading them several times.
You're not alone. Overload resolution is one of the most difficult areas of C++. Makes templates look easy.
Anyway, Eric, I had a question regarding your technique. It looks like the technique is not going to work with functors that have templated operator() In this case the template will happily eat arguments of any type, even the ones that it's not supposed to be called with. The error will not be detected during instantiation of can_be_called<> but when the functor is actually called. So, for example,
template <typename Fun, typename Arg1, typename Arg2> bool CanBeCalled(Fun const &, Arg1 const &, Arg2 const &) { return can_be_called<Fun, Arg1, Arg2>::result; }
CanBeCalled(bind(main, _1, _2), string(), complex());
Will produce "true".
As it should, IMO. bind() returns a function object that has an operator() that accepts the specified arguments.
But this: bind(main, _1, _2)(string(), complex());
Will generate a compile-time error.
Yup. :-(
Do you have any other tricks up your sleeve to solve it?
The only solution would be to modify the bind function object so that its operator() refused to accept arguments that its bound function doesn't also accept. This can be done with SFINAE using something akin to can_be_called. I'm not suggesting that such a change be made to Boost.Bind, but it would have one advantage: if users try to pass unacceptable arguments, the resulting error would point to the offending line in *their* code rather than someplace deep in Boost.Bind. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
The only solution would be to modify the bind function object so that its operator() refused to accept arguments that its bound function doesn't also accept. This can be done with SFINAE using something akin to can_be_called. I'm not suggesting that such a change be made to Boost.Bind, but it would have one advantage: if users try to pass unacceptable arguments, the resulting error would point to the offending line in *their* code rather than someplace deep in Boost.Bind. Can can_be_called become a first class Boost citizen in type_traits or some such ? Sounds like there is a substantial number of use cases in which it may help.
-- ___________________________________________ Joel Falcou - Assistant Professor PARALL Team - LRI - Universite Paris Sud XI Tel : (+33)1 69 15 66 35

On 12/20/2009 9:10 PM, joel falcou wrote:
Eric Niebler wrote:
The only solution would be to modify the bind function object so that its operator() refused to accept arguments that its bound function doesn't also accept. This can be done with SFINAE using something akin to can_be_called. I'm not suggesting that such a change be made to Boost.Bind, but it would have one advantage: if users try to pass unacceptable arguments, the resulting error would point to the offending line in *their* code rather than someplace deep in Boost.Bind.
Can can_be_called become a first class Boost citizen in type_traits or some such ? Sounds like there is a substantial number of use cases in which it may help.
Are you volunteering? :-) Might be a good addition to Function_traits. I imagine an interface like: can_be_called< Fun(Arg0, Arg1) > Or maybe callable, or can_be_invoked, or invokable, or callable_with_args, or ... callable_with_args ain't so bad. Yes, I think this would be a good addition. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 12/21/2009 11:36 AM, Eric Niebler wrote:
On 12/20/2009 9:10 PM, joel falcou wrote:
Can can_be_called become a first class Boost citizen in type_traits or some such ? Sounds like there is a substantial number of use cases in which it may help.
Are you volunteering? :-) Might be a good addition to Function_traits. I imagine an interface like:
can_be_called< Fun(Arg0, Arg1) >
Or maybe callable, or can_be_invoked, or invokable, or callable_with_args, or ... callable_with_args ain't so bad. Yes, I think this would be a good addition.
I had some time, so I knocked together a simple implementation and some test cases. This ignores things like calling convention, but mostly works. It would need someone to finish it, flesh out the test cases and add documentation. I've opened a feature request against the Function_types library and attached the code as a starting point: https://svn.boost.org/trac/boost/ticket/3783 -- Eric Niebler BoostPro Computing http://www.boostpro.com
participants (17)
-
Andy Venikov
-
Barend Gehrels
-
Chard
-
Daniel James
-
David Abrahams
-
David Bergman
-
Edward Diener
-
Eric Niebler
-
Frédéric Bron
-
joel falcou
-
Joel.Falcou@lri.fr
-
Mathias Gaunard
-
Maxime van Noppen
-
OvermindDL1
-
Patrick Horgan
-
Paul A. Bristow
-
Steven Watanabe