Indiana Unversity logo[ConceptGCC]

ConceptGCC :

Self referential concepts and infinite loops in conceptg++

From: tom.honermann_at_[hidden]
Date: 2007-03-18 00:25:48


Hello all!

I've been playing with Alpha 5 of ConceptGCC on RedHat Linux EL4 in order to validate a design for polytypic containers and iterators (ie, a container that holds objects of different types with iterator classes for iterating through the polytypic members).

The PolytypicSequenceIterator concept specifies an 'operator++' which returns another type that models PolytypicSequenceIterator, or a type modelling PolyTypicSequenceIteratorEnd representing the end of the sequence. This is resulting in two issues:
1: Need for an || constraint - which ConceptGCC doesn't currently support (and may never considering current thinking on support of this feature)
2: Having a concept specify a member type that models the same concept is causing 'conceptg++' to go into an infinite loop (see below). I was hoping I might be able to use 'late_check' to work around this, but either support for 'late_check' in ConceptGCC is not complete, or my understanding of 'late_check' is incomplete. Additionally, it sounds like the design of 'late_check' is up for re-consideration.

Consider the following code:

#include <concepts>

concept PolytypicSequenceIteratorEnd<typename T> {
};

concept PolytypicSequenceIterator<typename T> {
        typename next_iterator = T::next_iterator;
        where PolytypicSequenceIterator<next_iterator> || PolytypicSequenceIteratorEnd<next_iterator>;

        next_iterator operator++(const T&);
};

concept PolytypicSequence<typename T> {
        PolytypicSequenceIterator iterator;
        PolytypicSequenceIteratorEnd iterator_end;

        iterator T::begin();
        iterator_end T::end();
};

template<PolytypicSequence sequence>
void PolytypicSequenceVisitor(sequence s) {
        PolytypicSequenceVisitor(s.begin());
}

template<PolytypicSequenceIterator iterator>
void PolytypicSequenceVisitor(iterator i) {
        PolytypicSequenceVisitor(++i);
}

template<PolytypicSequenceIteratorEnd iterator_end>
void PolytypicSequenceVisitor(iterator_end i) {
}

When I attempt to compile this ('conceptg++ test.cpp -o test'), I get this error message:
    test.cpp:8: error: expected `;' before ?||? token
And then 'conceptg++' hangs. Further investigation reveals that 'cc1plus' appears to be stuck in infinite recursion. Reversing the expressions on either side of the '||' constraint avoids the infinite recursion, but I suspect that is because the right side of the expression is never evaluated.

Attaching with 'gdb' gives me a stack trace like:
(gdb) where
#0 0x0809b39b in comptypes (t1=0xb79a8bdc, t2=0xb77c0bdc, strict=0) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/typeck.c:1023
#1 0x0809b359 in comptypes (t1=0xb79a8c38, t2=0xb77c0c38, strict=0) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/typeck.c:1142
#2 0x080645da in template_args_equal (ot=Variable "ot" is not available.
) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:4201
#3 0x0806463d in comp_template_args (oldargs=0xb79abcf0, newargs=0xb77c4930)
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:4224
#4 0x0809b165 in comptypes (t1=0xb79a8c94, t2=0xb77c0c94, strict=0) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/typeck.c:1075
#5 0x0809b359 in comptypes (t1=0xb79a8cf0, t2=0xb77c0cf0, strict=0) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/typeck.c:1142
#6 0x080645da in template_args_equal (ot=Variable "ot" is not available.
) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:4201
#7 0x0806463d in comp_template_args (oldargs=0xb79abde0, newargs=0xb77c4a20)
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:4224
<Skipped lots and lots of frames...>
#5538 0x0806fae2 in expand_nested_requirements (model_id=0xb792e8fc) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11711
#5539 0x0806fbd9 in expand_where_clause (where_clause=0xb792f4c8, from_nested=1 '\001')
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11796
#5540 0x0806fae2 in expand_nested_requirements (model_id=0xb792e844) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11711
#5541 0x0806fbd9 in expand_where_clause (where_clause=0xb792f3d8, from_nested=1 '\001')
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11796
#5542 0x0806fae2 in expand_nested_requirements (model_id=0xb792e78c) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11711
#5543 0x0806fbd9 in expand_where_clause (where_clause=0xb792f2e8, from_nested=1 '\001')
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11796
#5544 0x0806fae2 in expand_nested_requirements (model_id=0xb792e6d4) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11711
#5545 0x0806fbd9 in expand_where_clause (where_clause=0xb792f1f8, from_nested=0 '\0')
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11796
#5546 0x0806fce8 in process_requirement (requirement=0xb792f1f8, expand=1 '\001')
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/pt.c:11839
#5547 0x08095e4a in cp_parser_declaration (parser=0xb7d01e6c) at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/parser.c:15457
#5548 0x080966de in cp_parser_declaration_seq_opt (parser=0xb7d01e6c)
    at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/parser.c:7046
#5549 0x08096d13 in c_parse_file () at ../../conceptgcc-4.1.1-alpha-5/gcc/cp/parser.c:2717
#5550 0x080ecbb0 in c_common_parse_file (set_yydebug=0) at ../../conceptgcc-4.1.1-alpha-5/gcc/c-opts.c:1159
#5551 0x08342eac in toplev_main (argc=14, argv=0xbfe56d24) at ../../conceptgcc-4.1.1-alpha-5/gcc/toplev.c:991
#5552 0x080f3f67 in main (argc=14, argv=0xbfe56d24) at ../../conceptgcc-4.1.1-alpha-5/gcc/main.c:35

I would very much appreciate any suggestions on how to handle this design using concepts. I've been trying to think of a way to avoid the need for a self-referential concept here, but I haven't been able to come up with anything that doesn't negate many of the benefits of using concepts in the first place. I'm still very new at designing for concepts, so any suggestions are more than welcome!

Thanks for all the hard work you all are doing!
Tom.