Boost logo

Boost :

Subject: Re: [boost] C++11 decltype/SFINAE puzzler
From: Eric Niebler (eric_at_[hidden])
Date: 2012-08-12 22:50:57


On 8/11/2012 6:23 PM, paul Fultz wrote:
>
>
>> I spent some time playing with this today. Attached is my best shot. The
>> basic idea is to change the RETURNS macro to -- in addition to declaring
>> the trailing return type and the function body -- also define an
>> implicit conversion to a function pointer. That gets selected as the
>> function called in the case that sfinae fails. That function returns a
>> sfinae_error that contains some useful information: the text of the
>> expression that failed to compile, the file and line number of the
>> sfinae failure, and the types of the function parameters (mangled,
>> unfortunately).
>>
> Unfortunately, this results in a run-time error instead of compile-time.

Right. It can be easily turned into a compile-time error by
static_assert'ing that the function's return type is not sfinae_error,
but the compiler error wouldn't be informative. You'd have to run to
code to see the error.

I was hoping to have a way to transport the error to an API boundary and
reporting it there, instead of presenting users with an imposing
template instantiation backtrace, but that might not be possible.

>> Can anybody do better?
>
> Attached is code that does present a compile-time error. It uses a function
> adaptor called `sfinae_error`. This will force sfinae success on the expression
> type dedcution by using a fail-through type. The fail through type doesn't
> matter since we know the function call will produce a compile error either way.
>
> So now, the `S0` class can be defined like this:
>
> struct S0_sfinae {
> template<typename T>
> auto operator()(T t) const RETURN( t + 1 )
> };
>
> typedef sfinae_error<S0_sfinae> S0;
>
> Then when you try to call it like this:
>
> struct foo {};
> S2()(foo());
>
> Clang will output the error inside of `sfinae_error` function adaptor with a
> full backtrace. At the bottom it will say:
>
> 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 )
>
> Which is what you want. Futhermore, this can be used even when there are
> multiple overloads in the `S0` class.

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.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk