> 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.
> 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.