
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