On Jan 11, 2014, at 2:55 PM, TONGARI J
Hi,
2014/1/12 Hui Li
I've implemented a few traits classes (code attached below) that, for a given callable-type T, and a set of Args..., detects whether the function call T::operator()(Args...) would be (1) valid, (2) ambiguous, or (3) none is viable. where T is allowed to have arbitrary overloaded operator()'s.
This could be useful for programmers who want to (1) make the function call only when it's valid, (2) generate customized error/warning messages when it's ambiguous, or handle/redirect it without getting an ambiguous compiler error, and (3) redirect non-viable calls to some default behavior, which can be different than how it's handled when the call is ambiguous.
If people are interested, I suppose this could be a useful addition to TypeTraits. I would appreciate any feedback!
For clarity, the implementation and demonstration attached below is written in c++11. It can be easily ported to c++98/03 compilers by using TypeTratis to replace the std type traits, BOOST_TYPEOF_KEYWORD to replace decltype, and Boost.Preprocessor to generate code for arbitrary arity.
It's interesting that you use ambiguity to distinguish the types. Anyway, your code doesn't support function(pointer) which is also Callable, and... are you sure your approach can be ported back to C++03 where there's no SFINAE on expression?
SFINAE on expression is not important in my approach. Since the has_compatible_callback merely uses has_valid_call, and my has_valid_call does the same thing as your has_call (besides the return type), i'm quite certain we can use your has_call for it's implementation and should be able to port to whatever compiler that works with your has_call.
FWIW, I have my has_call implementation: https://github.com/jamboree/boost.has_call which works for both C++11/03.
Very interesting, I will look into it, and see if i can switch to your has_call so that mine works on gcc4.3 (which I'm guessing is one of the compilers that don't support SFINAE on expression?)
I have real world usage of has_call (or has_valid_call in yours), but I don't have the need of has_ambiguous_call so far.
I have real world use for has_compatible_call, because has_call was insufficient in detecting ambiguous callback overloads provided by user defined classes (out of my control since I'm writing a library), in which case I want to generate a compiler error rather than using some default handler.
For example,
// in my real world application, there are other make_the_call overloads that make it more interesting than in this demonstration
template < typename E, typename T > // T is some user-defined class outside the library
typename std::enable_if<
has_valid_call
::type make_the_call(const E& e, T& t) { t(e); // if the call is ambiguous, the user must, and will, get a compiler error here // if we had used just has_valid_call in the enable_if, it would turn an erroneous ambiguity into a no-call // which would be very very wrong }
// default no-op behavior
template < typename E, typename T >
typename std::enable_if<
has_no_viable_call
::type make_the_call(const E& e, T& t) { // do nothing }
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost