[Boost][enable_if] SFINAE and decltype

Hi all, I'm having a hard time trying to figure out how to make a code like this to improve error messages through static_assert. I want that when the function instantiation fails, the other function's static assert fails. I don't know how to do it. I began with something like this: template <class Range, class T> Range find(Range && haystack, const T & elem) { static_assert(std::is_convertible<decltype (elem == haystack.front())>::value, "elem and haystack must be equality comparable"); while (!haystack.empty() && !(haystack.front() == elem)) haystack.popFront(); return haystack; } But that didn't work since when decltype is applied to an invalid expression, SFINAE doesn't trigger in the function body. So now I'm trying an alternative like this, but I don't know how to express it: template <class Range, class T> Range find(Range && haystack, const T & elem, decltype (elem == haystack.front()) * = 0) { while (!haystack.empty() && !(haystack.front() == elem)) haystack.popFront(); return haystack; } template <class Range, class T> Range find(Range && haystack, const T & elem, !decltype (elem == haystack.front()) * = 0) { static_assert(..., "haystack.front() and elem must be equality comparable"); return haystack; } I can't figure out how to make it work. I also tried with boost::enable_if but the problem is that a bool expression doesn't have a ::value member. Could anyone suggest me THE SIMPLEST and most readable way to make this work? Thanks in advance. P.S.: By the way, I also tried structs and partial specialization, but no luck.

On Thu, 28 Apr 2011, Germán Diago wrote:
Hi all,
I'm having a hard time trying to figure out how to make a code like this to improve error messages through static_assert. I want that when the function instantiation fails, the other function's static assert fails. I don't know how to do it. I began with something like this:
template <class Range, class T> Range find(Range && haystack, const T & elem) { static_assert(std::is_convertible<decltype (elem == haystack.front())>::value, "elem and haystack must be equality comparable"); while (!haystack.empty() && !(haystack.front() == elem)) haystack.popFront(); return haystack; }
But that didn't work since when decltype is applied to an invalid expression, SFINAE doesn't trigger in the function body.
So now I'm trying an alternative like this, but I don't know how to express it:
template <class Range, class T> Range find(Range && haystack, const T & elem, decltype (elem == haystack.front()) * = 0) { while (!haystack.empty() && !(haystack.front() == elem)) haystack.popFront(); return haystack; }
template <class Range, class T> Range find(Range && haystack, const T & elem, !decltype (elem == haystack.front()) * = 0) { static_assert(..., "haystack.front() and elem must be equality comparable"); return haystack; }
If you want the function to fail anyway, why not use the first version (that doesn't SFINAE on errors)? Otherwise, try changing your !decltype version to: template <class Range, class T> Range find(Range && haystack, const T& elem, ...) { // body } I think that gets the specialization order correct, but I'm not completely sure. -- Jeremiah Willcock

If you want the function to fail anyway, why not use the first version (that doesn't SFINAE on errors)? Otherwise, try changing your !decltype version to:
template <class Range, class T> Range find(Range && haystack, const T& elem, ...) { // body }
The problem is that I want meaningful error messages, and for that the assertion should be printed when compiling but it does not.
-- Jeremiah Willcock _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Germán Diago
-
Jeremiah Willcock