Re: Help with Template-Template and Mixin Polymorphism
On Aug 9, 11:38 pm, Greg Herlihy <gre...@pacbell.net> wrote:
My rule of thumb about programming with C++ templates has
always been, "if
the template code compiles - then the code is correct." :-).
[...]
// redeclared foo() non-pure in order to compile
virtual key_type foo( value_type) {};// = 0;
Thanks for all the help Greg. Since I've been compiling my test code
with g++ it has been more explicit about the template/typename usage.
However, adding an implementation for the pure virtual breaks the
polymorphism. To wit, if we add implementations to foo:
#include <iostream>
template <class E, class Y>
struct Z
{
typedef E key_type;
typedef Y value_type;
};
template <template <class, class> class X1>
struct G
{
template <class E2, class Y2>
struct G1
{
typedef G1 self;
typedef X1<E2, Y2> type;
typedef typename X1<E2, Y2>::key_type key_type;
typedef typename X1<E2, Y2>::value_type
value_type;
};
};
template <template <class, class> class X2>
struct G<G<X2>::template G1>
{
template <class E3, class Y3>
struct G1
{
typedef X2<E3, Y3> container_type;
typedef typename container_type::key_type key_type;
typedef typename container_type::value_type value_type;
};
};
template <template <class, class> class X, class Y>
struct A
{
typedef A<X, Y> generic_type;
typedef G<X> H;
typedef typename G<X>::template G1<A*,Y>::self F;
typedef typename G<X>::template G1<A*,Y>::key_type
key_type;
typedef typename F::value_type value_type;
A() {}
virtual ~A() {}
// redeclared foo() non-pure in order to compile
virtual key_type foo(value_type) { return 0; }// = 0;
};
template <class Y>
struct B : public virtual A< G<Z>::template G1, Y>
{
typedef typename A<G<Z>::G1, Y>::key_type key_type;
typedef typename A<G<Z>::G1, Y>::key_type value_type;
B() {}
virtual ~B() {}
virtual key_type foo(value_type) { return this; }
};
template <class Y, template <class> class P = B>
struct C : public virtual A<P<Y>::H::template G1, Y>,
private P<Y>
{
typedef A<P<Y>::H::template G1, Y> my_base_type;
typedef my_base_type generic_type;
C() {}
C( const C&) {}
virtual ~C() {}
const C& operator=(const C& ) { return *this; }
};
int main()
{
C<int> c;
C<int>::generic_type *pc = &c;
C<int>::generic_type *pfoo = pc->foo(3);
std::cout << std::hex << (int)pfoo << std::endl;
}
The output is not the address of B, but in fact 0. So, leaving A::foo
pure virtual is handy since it correctly detected that the compiler
thinks C's A is different than B's A, when they shouldn't be. *sigh*
Jeffrey.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]