Boost logo

Boost :

Subject: Re: [boost] [guidelines] why template errors suck
From: Eric Niebler (eric_at_[hidden])
Date: 2010-09-27 11:05:44


On 9/26/2010 2:24 PM, John Bytheway wrote:
> On 25/09/10 04:51, Eric Niebler wrote:
>> On 9/24/2010 9:37 PM, David Abrahams wrote:
>>> The real challenge would be making it easy to write new concepts. Right now the usage requirements are simple to state, but if you wanted static_assert to fire,
>>> we'd need to use checks that don't cause errors, e.g. instead of:
>>>
>>> same_type(*i++,v); // postincrement-dereference returning value_type
>>>
>>>
>>> you'd have to write something like:
>>>
>>> static_assert(
>>> has_postincrement<InputIterator>::value, "not postincrementable");
>>> static_assert(
>>> has_postincrement_deref<InputIterator>::value, "not dereferenceable");
>>> static_assert(
>>> is_same<
>>> postincrement_deref<InputIterator>::type, InputIterator::value_type
>>> >::value,
>>> "postincrement dereference doesn't return value_type");
>>>
>>> Well, in all, I guess I like the rigor but it's not very compatible with the loosey-goosey C++03 way of specifying concepts <pines for real concept support>.
>>
>> Blech. Can C++0x SFINAE on expressions make this any nicer? The idea is
>> to be able to text expressions for well-formedness without causing a
>> compile error. Then we'd need a way to chain these expressions to make
>> lists of requirements. Maybe PP sequences consisting of valid
>> expressions? Is there a compiler that implements this yet so we can play
>> with it?
>
> I decided to have a first stab at something along these lines (with g++
> 4.4 in C++0x mode). I think my experiment shows promise. I tweaked a
> cut-down version of the Boost.ConceptCheck InputIterator concept thus:
>
> template<typename X>
> class InputIterator {
> private:
> typedef std::iterator_traits<X> t;
> public:
> typedef typename t::value_type value_type;
> ~InputIterator()
> {
> verify::check(verify::same_type(*i++, v));
> }
> private:
> verify::example<X> i;
> verify::example<value_type> v;
> };
>
> Here verify::same_type, i, and v are all Proto terminals, so the
> expression verify::same_type(*i++, v) is a Proto expression tree.

Wow, I never would have thought to use Proto for this!

> the
> verify::check function traverses this tree and pulls out the first
> problematic thing and causes a pertinent static_assertion to fail about
> it. So, for example, using the following classes:
>
> struct A {
> typedef std::random_access_iterator_tag iterator_category;
> typedef int value_type;
> typedef ptrdiff_t difference_type;
> typedef int* pointer;
> typedef int& reference;
> };
>
> struct B : A {
> B operator++(int);
> };
>
> struct C : A {
> C operator++(int);
> double const& operator*();
> };
>
> struct D : A {
> D operator++(int);
> int const& operator*();
> };
>
> and checking each of them with a statement like:
>
> VERIFY_MODELS_CONCEPT(InputIterator<A>);
>
> yields the following compiler errors, which I think are pretty succinct
> and pertinent:

<snip>

> Does this sound like a worthwhile thing to attempt? I'd be willing to
> give it a try.

John, this sounds terrific. I don't think I grok in full what you're
doing but it sounds worthwhile. One thing to consider is whether you can
use SFINAE on expressions to validate concepts without causing hard
errors. Then we might be able to get some approximation of concept-based
overloading.

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