Boost logo

Boost :

Subject: Re: [boost] C++11 decltype/SFINAE puzzler
From: Eric Niebler (eric_at_[hidden])
Date: 2012-08-13 16:03:33

On 8/12/2012 7:50 PM, Eric Niebler wrote:
> Great! And very simple. It doesn't move the error close to the API
> boundary, but other than that, it fits the bill. Thanks. If I end up
> using this technique in my code, I will credit you.

I think I have a very nice solution now. It combines my earlier approach
with with Paul Fritz's. See the attached.

You define your callables with the RETURNS macro and a try_call function
object wrapper, like this:

    struct S0
        template<typename T>
        auto operator()(T t) const RETURN( t + 1 )

    struct S1
        template<typename T>
        auto operator()(T t) const RETURN( try_call<S0>()(t) )

    struct S2
        template<typename T>
        auto operator()(T t) const RETURN( try_call<S1>()(t) )

Then, you simply invoke your function object:

    auto i = S2()(32); // ok
    auto x = S2()(foo()); // compile-time error

The compile error is transported to the API boundary. The result is a
very short and precise error message about the cause of the failure.
Clang gives this:

> $ /usr/local/bin/clang++ -std=gnu++11 sfinae_error.cpp
> sfinae_error.cpp:28:26: error: no matching function for call to object of type 'S0'
> typedef decltype(std::declval<Fun>()(std::declval<Args>()...)) type;
> ^~~~~~~~~~~~~~~~~~~
> sfinae_error.cpp:91:14: note: in instantiation of member function 'sfinae_error<S0 (foo &)>::what'
> requested here
> auto x = S2()(foo());
> ^
> sfinae_error.cpp:70:10: note: candidate template ignored: substitution failure [with T = foo]:
> invalid operands to binary expression ('foo' and 'int')
> auto operator()(T t) const RETURN( t + 1 )
> ^ ~~~~~~~~~~~~~~~
> 1 error generated.

Note that no information about the intermediate calls (S2, S1) shows up
in the backtrace. Just the error you care about.

GCC-4.7 gives a similarly terse error message. This, I think, is what
I've been looking for.

Eric Niebler
BoostPro Computing

Boost list run by bdawes at, gregod at, cpdaniel at, john at