Boost logo

Boost :

Subject: Re: [boost] dramatically improved template error messages
From: Eric Niebler (eric_at_[hidden])
Date: 2012-08-16 12:01:40


On 8/16/2012 6:44 AM, Andrew Sutton wrote:
>> To avoid redundant errors, you must dispatch to an empty implementation
>> on concept check failure:
>>
>> template <typename I, typename T>
>> I find_impl(std::true_type, I first, I last, const T& value) {
>> while (first != last && *first != value) ++first;
>> }
>>
>> template <typename I, typename T>
>> I find_impl(std::false_type, I first, I last, const T& value) {
>> static_assert (Input_iterator<I>(), "");
>> }
>>
>> template <typename I, typename T>
>> I find(I first, I last, const T& value) {
>> find_impl(Input_iterator<I>(), first, last, value);
>> }
>>
>> Not if you use the trick above.
>
> Interesting... That looks like it will work.

It should. It's an old trick I use in a bunch of places. I even wrote
about it here:

http://cpp-next.com/archive/2010/09/expressive-c-why-template-errors-suck-and-what-you-can-do-about-it/

(See the section "Avoid Follow-on Errors")

FWIW, the code I sent above can be improved. The static_assert should be
in find(), not find_impl. That will remove one frame of the stack
backtrace. And I think the find_impl that takes false_type only needs to
be forward-declared. That way you don't need to mock up a return call
that will never be used.

> Do you still need the
> sfinae_error class to get shallow errors? I'm guessing not in these
> cases.

Depends. If you already have an easy way to implement your concept
classes so that checking against types that don't model the concept
doesn't cause a hard error, then you can forget about the try_call
wrapper. Otherwise, it's still useful to you, even though you wouldn't
be making use of the short error reporting mechanism.

>> You only have the guard the calls that add constraints. Other calls will
>> simply propagate sfinae_error and don't need to be guarded. (In my
>> example, S2 doesn't need to guard the call to S1, but S1 must guard S0
>> because it adds an Addable constraint.) Also, you can guard your
>> function object once by defining it with try_call_wrapper, so it doesn't
>> need to be guarded everywhere.
>>
>> Just apply more force. :-)
>
> Indeed :)
>
> Side note: sfinae_error is a bad name in a worse way than how "PIN
> number" is redundant. It's not an error, but it is.
> substitution_failure or subst_failure might be better choices.

You're right. Thanks.

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