decorator.cc
):// this file goes with the paper: // Alexandre Duret-Lutz, Thierry Geraud, and Akim Demaille. // Generic Design Patterns in C++. In the Proceedings of the 6th // USENIX Conference on Object-Oriented Technologies and Systems (COOTS), // pages 189-202, San Antonio, Texas, USA, January-February 2001. #include <iostream> using std::cout; using std::endl; class ConcreteComponent { public: void Operation() { cout << "ConcreteComponent::Operation" << endl; } }; template<class C> class ConcreteDecoratorA : public C { public: void Operation() { C::Operation(); addedState = 1; } protected: int addedState; }; template<class C> class ConcreteDecoratorB : public C { public: void Operation() { C::Operation(); AddedBehaviour(); } protected: void AddedBehaviour() { cout << "ConcreteDecoratorB::AddedBehaviour" << endl; } }; int main() { ConcreteDecoratorB<ConcreteComponent> cb; cb.Operation(); } |
templmeth.cc
):// this file goes with the paper: // Alexandre Duret-Lutz, Thierry Geraud, and Akim Demaille. // Generic Design Patterns in C++. In the Proceedings of the 6th // USENIX Conference on Object-Oriented Technologies and Systems (COOTS), // pages 189-202, San Antonio, Texas, USA, January-February 2001. #include <iostream> using std::cout; using std::endl; template<class I> class SuperiorOf { protected: SuperiorOf() { } I& Self() { return static_cast<I&>(*this); } }; template<class I> class AbstractClass : public SuperiorOf<I> { public: void TemplateMethod() { // ... PrimitiveOperation1(); // ... PrimitiveOperation2(); // ... } void PrimitiveOperation1() { Self().PrimitiveOperation1_impl(); } void PrimitiveOperation2() { Self().PrimitiveOperation2_impl(); } }; class ConcreteClass : public AbstractClass<ConcreteClass> { public: void PrimitiveOperation1_impl() { cout << "ConcreteClass::PrimitiveOperation1" << endl; } void PrimitiveOperation2_impl() { cout << "ConcreteClass::PrimitiveOperation2" << endl; } }; int main() { ConcreteClass obj; obj.TemplateMethod(); } |
vertical.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // ``Vertical'' recurring hierarchy: // // A* // | // B* // | // C* // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> class A : public Void< A<I> > { public: void echo() { cout << "A" << endl; } }; template<class I = Bottom> class B : public A< B<I> > { public: void echo() { cout << "B" << endl; } }; template<class I = Bottom> class C : public B< C<I> > { public: void echo() { cout << "C" << endl; } }; // // strong statically typed foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { to_exact(a).echo(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { A<> a; foo(a); B<> b; foo(b); C<> c; foo(c); } |
horizontal.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // ``Horizontal'' recurring hierarchy: // // A* // / \ // B1* B2* // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> class A : public Void< A<I> > { public: void echo() { cout << "A" << endl; } }; template<class I = Bottom> class B1 : public A< B1<I> > { public: void echo() { cout << "B1" << endl; } }; template<class I = Bottom> class B2 : public A< B2<I> > { public: void echo() { cout << "B2" << endl; } }; // // strong statically typed foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { to_exact(a).echo(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { A<> a; foo(a); B1<> b1; foo(b1); B2<> b2; foo(b2); } |
exact_type.hh
):#ifndef EXACT_TYPE_HH #define EXACT_TYPE_HH // // Top, Bottom, and Void // ////////////////////////////////////////////////////////////////////// class Top { protected: Top() {} }; class Bottom { private: Bottom(); }; template<class I = Bottom> class Void : public Top { protected: Void() {} }; // // inferior traits // ////////////////////////////////////////////////////////////////////// template<class> struct inferior; template<template<class> class C, class I> struct inferior< C<I> > { typedef I type; }; // special mixin: template<template<template<class> class, class> class M, template<class> class S, class I> struct inferior< M<S,I> > { typedef I type; }; // // exact traits // ////////////////////////////////////////////////////////////////////// namespace misc { template<class T> struct find_exact; template<class T, class I> struct helper { typedef typename find_exact<I>::type type; }; template<class T> struct helper<T, Bottom> { typedef T type; }; template<class T> struct find_exact { typedef typename inferior<T>::type I; typedef typename helper<T,I>::type type; }; } template<class T> struct exact { typedef typename misc::find_exact<T>::type type; }; // // exact proc // ////////////////////////////////////////////////////////////////////// template<class T> typename exact<T>::type* to_exact(Void<T>* ptr) { return static_cast<typename exact<T>::type*>(ptr); } template<class T> const typename exact<T>::type* to_exact(const Void<T>* ptr) { return static_cast<const typename exact<T>::type*>(ptr); } template<class T> typename exact<T>::type& to_exact(Void<T>& ref) { return static_cast<typename exact<T>::type&>(ref); } template<class T> const typename exact<T>::type& to_exact(const Void<T>& ref) { return static_cast<const typename exact<T>::type&>(ref); } // // solve_cast traits // ////////////////////////////////////////////////////////////////////// template<template<class> class C, class T> C<T>& solve_cast(C<T>& obj) { return obj; } template<template<class> class C, class T> const C<T>& solve_cast(const C<T>& obj) { return obj; } template<template<class, class> class C, class T1, class T2 > C<T1,T2>& solve_cast(C<T1,T2>& obj) { return obj; } template<template<class, class> class C, class T1, class T2 > const C<T1,T2>& solve_cast(const C<T1,T2>& obj) { return obj; } template<template<class, class, class> class C, class T1, class T2, class T3 > C<T1,T2,T3>& solve_cast(C<T1,T2,T3>& obj) { return obj; } template<template<class, class, class> class C, class T1, class T2, class T3 > const C<T1,T2,T3>& solve_cast(const C<T1,T2,T3>& obj) { return obj; } #endif |
crtp-pb.cc
):#include <iostream> using std::cout; using std::endl; // // ``Deep'' hierarchy and the Curiously Recurring Template Pattern // // A // / \ // B1 B2 // | // B20 // ////////////////////////////////////////////////////////////////////// template<class T> struct A { T& self() { return static_cast<T&>(*this); } void m() { self().n(); // ... } }; struct B1 : public A<B1> { void n() { cout << "B1::n" << endl; } }; struct B2 : public A<B2> { void n() { cout << "B2::n" << endl; } }; struct B20 : public B2 { void n() { cout << "B20::n" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(T& a) { a.m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B1 b1; foo(b1); // B1::n B2 b2; foo(b2); // B2::n B20 b20; foo(b20); // B2::n! } |
crtp-sol.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // ``Deep'' recurring hierarchy and the CRTP // // A* // / \ // B1* B2* // | // B20* // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct A : public Void< A<I> > { void m() { to_exact(this)->n(); } }; template<class I = Bottom> struct B1 : public A< B1<I> > { void n() { cout << "B1::n" << endl; } }; template<class I = Bottom> struct B2 : public A< B2<I> > { void n() { cout << "B2::n" << endl; } }; template<class I = Bottom> struct B20 : public B2< B20<I> > { void n() { cout << "B20::n" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(T& a) { a.m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B1<> b1; foo(b1); // B1::n B2<> b2; foo(b2); // B2::n B20<> b20; foo(b20); // B20::n } |
bound-off.cc
):// // foo with no bounded quantification // ////////////////////////////////////////////////////////////////////// template<class T> void foo(T& a) { a.m(); // (*) } // // two structs: one conforms, the other does not // ////////////////////////////////////////////////////////////////////// struct B1 { void m() { // ... } }; struct Z { }; // // main // ////////////////////////////////////////////////////////////////////// int main() { B1 b; foo(b); // ok Z z; foo(z); // => error at line (*) } |
bound-on.cc
):#include "static_isa.h" // from http://oonumerics.org/tmpw00/mcnamara.html #include "exact_type.hh" // // a bound map to a struct and foo with bounded quantification // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct A : public Void< A<I> > { // structural_check: MAKE_TRAITS; template<class Self> static void check_structural() { void (Self::*_m)() const = &Self::m; (void)_m; } protected: ~A() { RequireBoth< I, A<I> >(); // means: // I is required to be a sub-class of A<I> // *and* structural checking is performed } }; template<class T> void foo(A<T>& a) { to_exact(a).m(); } // // two structs: one conforms, the other does not // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct B1 : public A< B1<I> > { void m() { // ... } }; struct Z { }; // // main // ////////////////////////////////////////////////////////////////////// int main() { B1<> b; foo(b); // ok Z z; foo(z); // error } |
overload-sol.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // bounds and concrete classes // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct D : public Void< D<I> > { protected: D() {} }; template<class I = Bottom> struct D1 : public D< D1<I> > { }; template<class I = Bottom> struct E : public Void< E<I> > { protected: E() {} }; template<class I = Bottom> struct E1 : public E< E1<I> > { }; template<class I = Bottom> struct F : public Void< F<I> > { protected: F() {} }; template<class I = Bottom> struct F1 : public F< F1<I> > { }; // // overloaded functions // ////////////////////////////////////////////////////////////////////// template<class T, class U> void bar(D<T>& d, E<U>& e) { cout << "bar(D,E)" << endl; } template<class T, class U> void bar(D<T>& d, F<U>& f) { cout << "bar(D,F)" << endl; } // // main // ////////////////////////////////////////////////////////////////////// int main() { D1<> d; E1<> e; bar(d,e); } |
overload-meta.cc
):#include <iostream> using std::cout; using std::endl; #include "static_isa.h" // // interfaces and concrete classes // ////////////////////////////////////////////////////////////////////// struct D { protected: D() {} }; struct D1 : public D { }; struct E { protected: E() {} }; struct E1 : public E { }; struct F { protected: F() {} }; struct F1 : public F { }; // // overloaded functions // ////////////////////////////////////////////////////////////////////// struct bar_DE { template<class D, class E> static void exec(D& d, E& e) { cout << "bar_DE::exec" << endl; } }; struct bar_DF { template<class D, class F> void exec(D& d, F& f) { cout << "bar_DF" << endl; } }; template<class D, class T> void bar(D& d, T& t) { typedef typename IF< Named<T,E>::valid, bar_DE, bar_DF >::RET bar_t; bar_t::exec(d, t); } // // main // ////////////////////////////////////////////////////////////////////// int main() { D1 d; E1 e; bar(d,e); } |
diamond.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // ``Diamond-shaped'' recurring hierarchy: // // A* // / \ // B1* B2* // \ / \ // C1* C2* // \ / // D* // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> class A : public Void< A<I> > { public: void echo() { cout << "A" << endl; } }; template<class I = Bottom> class B1 : public A< B1<I> > { public: void echo() { cout << "B1" << endl; } }; template<class I = Bottom> class B2 : public A< B2<I> > { public: void echo() { cout << "B2" << endl; } }; template<class I = Bottom> class C1 : public B1< C1<I> >, public B2< C1<I> > { public: void echo() { cout << "C1" << endl; } }; template<class I = Bottom> class C2 : public B2< C2<I> > { public: void echo() { cout << "C2" << endl; } }; template<class I = Bottom> class D : public C1< D<I> >, public C2< D<I> > { public: void echo() { cout << "D" << endl; } }; // // strong statically typed foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { to_exact(a).echo(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { D<> d; foo(solve_cast<B1>(d)); foo(solve_cast<C2>(d)); } |
mixin.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // some classes // ////////////////////////////////////////////////////////////////////// template< class I = Bottom > struct A : public Void< A<I> > { }; template< class I = Bottom > struct B1 : public A< B1<I> > { void m() const { cout << "B1::m" << endl; } void n() const { cout << "B1::n" << endl; } }; template< class I = Bottom > struct B2 : public A< B2<I> > { void m() const { cout << "B2::m" << endl; } }; // // mixins // ////////////////////////////////////////////////////////////////////// template< template<class> class S, class I = Bottom > struct Mixin : public S< Mixin<S,I> > { typedef S< Mixin<S,I> > Super; void m() const { cout << "Mixin::m" << endl; this->Super::m(); } }; template< template<class> class S, class I = Bottom > struct SubMixin : public Mixin<S, SubMixin<S,I> > { typedef Mixin<S, SubMixin<S,I> > Super; void m() const { cout << "SubMixin::m" << endl; this->Super::m(); } }; // // foo // ////////////////////////////////////////////////////////////////////// template< class T > void foo(A<T>& a) { to_exact(a).m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { Mixin<B1> b1; foo(b1); // gives: Mixin::m // B1::m SubMixin<B2> b2; foo(b2); // gives: SubMixin::m // Mixin::m // B2::m } |
color-pb.cc
):#include <iostream> using std::cout; using std::endl; // // Point // ////////////////////////////////////////////////////////////////////// struct Point { typedef Point This; Point(int x, int y) : x(x), y(y) { } bool operator==(const This& rhs) const { return x == rhs.x && y == rhs.y; } protected: int x, y; }; // // ColorPoint // ////////////////////////////////////////////////////////////////////// struct ColorPoint : public Point { typedef ColorPoint This; typedef Point Super; ColorPoint(int x, int y, int c) : Super(x, y), c(c) { } bool operator==(const This& rhs) const { return Super::operator==(rhs) && c == rhs.c; } protected: int c; }; // // foo // ////////////////////////////////////////////////////////////////////// void foo(const Point& p1, const Point& p2) { cout << (p1 == p2 ? "true" : "false") << endl; } // // main // ////////////////////////////////////////////////////////////////////// int main() { Point a(0,5); ColorPoint b(0,5,1); foo(a, b); // true! } |
color-sol.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // F_EQ // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct F_EQ : public Void< F_EQ<I> > { typedef F_EQ<I> This; bool operator==(const This& rhs) const { return to_exact(this)->eq(to_exact(rhs)); } }; // // operator!= // ////////////////////////////////////////////////////////////////////// template<class T> bool operator!=(const F_EQ<T>& lhs, const F_EQ<T>& rhs) { return ! lhs.operator==(rhs); } // // Point // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct Point : public F_EQ< Point<I> > { typedef Point<I> This; Point(int x, int y) : x(x), y(y) { } bool eq(const This& rhs) const { return x == rhs.x && y == rhs.y; } protected: int x, y; }; // // ColorPoint // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct ColorPoint : public Point< ColorPoint<I> > { typedef ColorPoint<I> This; typedef Point<This> Super; ColorPoint(int x, int y, int c) : Super(x, y), c(c) { } bool eq(const This& rhs) const { return Super::eq(rhs) && c == rhs.c; } protected: int c; }; // // foo // ////////////////////////////////////////////////////////////////////// template<class P> void foo(const Point<P>& p1, const Point<P>& p2) { cout << (p1 == p2 ? "true" : "false") << endl; } // // main // ////////////////////////////////////////////////////////////////////// int main() { Point<> a(0,5); ColorPoint<> b(0,5,1); ColorPoint<> c(0,5,1); foo(a, b); // error at compile-time foo(b, c); // true } |
contrav.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // First hierarchy // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct Base : public Void< Base<I> > { }; template<class I = Bottom> struct Derived : public Base< Derived<I> > { }; // // Second hierarchy with contravariant methods // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct A : public Void< A<I> > { template<class T> void m(Derived<T>& d) { to_exact(this)->m(d); } }; template<class I = Bottom> struct B1 : public A< B1<I> > { template<class T> void m(Base<T>& b) { cout << "A1::m" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { Derived<> d; a.m(d); } // // main // ////////////////////////////////////////////////////////////////////// int main() { A1<> a1; foo(a1); } |
stl-pb.cc
):#include <iostream> using std::cout; using std::endl; // // hierarchy // ////////////////////////////////////////////////////////////////////// struct B2 { void m() { cout << "B2::m" << endl; } }; struct B20 : public B2 { void m() { cout << "B20::m" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(T& a) { // ... a.m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B20 b; foo(b); // B20::m foo(static_cast<B2&>(b)); // B2::m! } |
stl-sol.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // reccurring hierarchy // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> struct A : public Void< A<I> > { protected: A() {} }; template<class I = Bottom> struct B2 : public A< B2<I> > { void m() { cout << "B2::m" << endl; } }; template<class I = Bottom> struct B20 : public B2< B20<I> > { void m() { cout << "B20::m" << endl; } }; // // foo'n bar // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& _a) { typedef typename exact< A<T> >::type A; A& a = to_exact(_a); // ... a.m(); } template<class T> void bar_with_upcast(B2<T>& b) { foo(b); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B20<> b; foo(b); // B20::m bar_with_upcast(b); // B20::m } |
rec-pb.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type.hh" // // inferior traits ---second part // this code is useless :( // ////////////////////////////////////////////////////////////////////// template<template<class, class> class C, class T, class I> struct inferior< C<T,I> > { typedef I type; }; template<template<class, class, class> class C, class T1, class T2, class I> struct inferior< C<T1,T2,I> > { typedef I type; }; // // recurring hierarchy // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> class A : public Void< A<I> > { }; // we have to explicitely specialize `inferior': template<class U, class I> struct B; template<class U, class I> struct inferior< B<U,I> > { typedef I type; }; // otherwise we get the following error: // // ambiguous class template instantiation for `struct inferior< B<int,Bottom> >' // candidates are: struct inferior< C<T,I> > // struct inferior< C<I> > template<class U, class I = Bottom> struct B : public A< B<U,I> > { void m() { cout << "B::m" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { to_exact(a).m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B<int> b; foo(b); } |
exact_type_vrec.hh
):#ifndef EXACT_TYPE_HH #define EXACT_TYPE_HH // // Top, Bot, rec, Bottom, and Void // ////////////////////////////////////////////////////////////////////// struct Top { protected: Top() {} }; struct Bot { private: Bot(); }; template<class> struct rec { }; typedef rec<Bot> Bottom; template<class I = Bottom> class Void : public Top { protected: Void() {} }; // // inferior traits // ////////////////////////////////////////////////////////////////////// template<class> struct inferior; template<class I> struct inferior< rec<I> > { typedef I type; }; template<template<class> class C, class I> struct inferior< C< rec<I> > > { typedef I type; }; template<template<class, class> class C, class T, class I > struct inferior< C<T, rec<I> > > { typedef I type; }; template<template<class, class, class> class C, class T1, class T2, class I > struct inferior< C<T1, T2, rec<I> > > { typedef I type; }; // // exact traits // ////////////////////////////////////////////////////////////////////// namespace misc { template<class T> struct find_exact; template<class T, class I> struct helper { typedef typename find_exact<I>::type type; }; template<class T> struct helper<T, Bot> { typedef T type; }; template<class T> struct find_exact { typedef typename inferior<T>::type I; typedef typename helper<T,I>::type type; }; } template<class T> struct exact { typedef typename misc::find_exact<T>::type type; }; // // exact proc // ////////////////////////////////////////////////////////////////////// template<class T> typename exact<T>::type* to_exact(Void<T>* ptr) { return static_cast<typename exact<T>::type*>(ptr); } template<class T> const typename exact<T>::type* to_exact(const Void<T>* ptr) { return static_cast<const typename exact<T>::type*>(ptr); } template<class T> typename exact<T>::type& to_exact(Void<T>& ref) { return static_cast<typename exact<T>::type&>(ref); } template<class T> const typename exact<T>::type& to_exact(const Void<T>& ref) { return static_cast<const typename exact<T>::type&>(ref); } // // solve_cast traits // ////////////////////////////////////////////////////////////////////// template<template<class> class C, class T> C<T>& solve_cast(C<T>& obj) { return obj; } template<template<class> class C, class T> const C<T>& solve_cast(const C<T>& obj) { return obj; } template<template<class, class> class C, class T1, class T2 > C<T1,T2>& solve_cast(C<T1,T2>& obj) { return obj; } template<template<class, class> class C, class T1, class T2 > const C<T1,T2>& solve_cast(const C<T1,T2>& obj) { return obj; } template<template<class, class, class> class C, class T1, class T2, class T3 > C<T1,T2,T3>& solve_cast(C<T1,T2,T3>& obj) { return obj; } template<template<class, class, class> class C, class T1, class T2, class T3 > const C<T1,T2,T3>& solve_cast(const C<T1,T2,T3>& obj) { return obj; } #endif |
rec-sol.cc
):#include <iostream> using std::cout; using std::endl; #include "exact_type_vrec.hh" // // recurring hierarchy // ////////////////////////////////////////////////////////////////////// template<class I = Bottom> class A : public Void< A< rec<I> > > { // `rec' inserted }; template<class U, class I = Bottom> struct B : public A< rec< B<U,I> > > { // `rec' inserted void m() { cout << "B::m" << endl; } }; // // foo // ////////////////////////////////////////////////////////////////////// template<class T> void foo(A<T>& a) { to_exact(a).m(); } // // main // ////////////////////////////////////////////////////////////////////// int main() { B<int> b; foo(b); } |