iterator_category> algorithm selection with cast operator

Hello, I've read the article of ranges vs. iterators from Andrei Alexandrescu and I've start to implement something similar and wanted to extend the idea to 2D grids (popFront, front, popLine). OK, I now s/g similar can be achieved using iterators(ranges) returning iterators(ranges) as the current item, I was just simple experimenting. Using the iterator_category concept empty structs are used to check, select functions at compile time. struct A {}; struct B : A {} void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } template<typename T> void foofoo( T ){ foo( getCategory<T>() ); } My first idea was to use multiple inheritance, but it result error (ambiguous call) struct A {}; struct B : A {}; struct A2 : A {}; struct B2 : A2, B {}; void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } void foo( A2 ) { alg3... specialized for A2 } void g() { B2 b; f(b); } // error: is it f(B) or f(A2) Than I've used cast operators and inheritance stating that, a B2 is mainly an A2 and secondly a B: struct A {}; struct B : A {}; struct A2 : A {}; struct B2 : A2 { operator B() { return B(); } }; void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } void foo( A2 ) { alg3... specialized for A2 } void g() { B2 b; f(b); } // shall call f(A2) So my question is that, is it a working method, or the whole concept is wrong ? Has anyone used something similar ? If so, is there some sample codes/results? Thank you, Gzp -- View this message in context: http://old.nabble.com/iterator_category%3E-algorithm-selection-with-cast-ope... Sent from the Boost - Dev mailing list archive at Nabble.com.

On 6/25/2010 8:11 AM, gzp wrote:
Hello,
[...]
Using the iterator_category concept empty structs are used to check, select functions at compile time. struct A {}; struct B : A {} void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } template<typename T> void foofoo( T ){ foo( getCategory<T>() ); }
My first idea was to use multiple inheritance, but it result error (ambiguous call) struct A {}; struct B : A {}; struct A2 : A {}; struct B2 : A2, B {};
void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } void foo( A2 ) { alg3... specialized for A2 } void g() { B2 b; f(b); } // error: is it f(B) or f(A2)
Than I've used cast operators and inheritance stating that, a B2 is mainly an A2 and secondly a B: struct A {}; struct B : A {}; struct A2 : A {}; struct B2 : A2 { operator B() { return B(); } };
void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } void foo( A2 ) { alg3... specialized for A2 } void g() { B2 b; f(b); } // shall call f(A2)
So my question is that, is it a working method, or the whole concept is wrong ? Has anyone used something similar ? If so, is there some sample codes/results?
The nice thing about using inheritance (which necessarily restricts your concept hierarchies to be linear) is that your conversions are automatically transitively closed. Conversions don't have this feature, i.e., if A -> B and B -> C via conversion operators, then it won't (necessarily) be the case that A -> C (where "->" means "is convertible to"); you'd have to add that conversion explicitly. This would affect tag dispatching, e.g., dispatch(boost::single_pass_traversal_tag); dispatch(boost::random_access_traversal_tag); f(Iterator it) { dispatch(boost::iterator_traversal< Iterator >::type()); } only works reliably because boost::bidirectional_traversal_tag -> boost::single_pass_traversal_tag, even though boost::bidirectional_traversal_tag only (directly) inherits from boost::forward_traversal_tag. Other than the above issues with transitive conversions, however, I believe using conversion operators suffice. - Jeff

At Fri, 25 Jun 2010 08:11:28 -0700 (PDT), gzp wrote:
My first idea was to use multiple inheritance, but it result error (ambiguous call) struct A {}; struct B : A {}; struct A2 : A {}; struct B2 : A2, B {};
void foo( A ) { alg1... } void foo( B ) { alg2... specialized for B } void foo( A2 ) { alg3... specialized for A2 } void g() { B2 b; f(b); } // error: is it f(B) or f(A2)
<snipp>
So my question is that, is it a working method, or the whole concept is wrong ?
Your best bet here is probably to use multiple _virtual_ inheritance struct A {}; struct B : virtual A {}; struct A2 : virtual A {}; struct B2 : virtual A2, virtual B {}; You might also want to check the generated code, though. It's conceivable (although probably not very important if so) that the compiler won't optimize away the tag structs. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
David Abrahams
-
gzp
-
Jeffrey Lee Hellrung, Jr.