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);
}
|