Runtime Concept 的模拟(4)
简化使用方法!
支持auto concept和non-auto concept。
支持引用类型concept和值类型concept。
已测试支持的编译器:
VC 7.1 (VC 2003)
VC 8.0 (VC 2005)
VC 9.0 (VC 2008)
GCC 3.4.2
GCC 4.2.3
基本原理:
1. 用类继承的方法生成vtable。
2. 用多继承来组合concept。
缺陷:
1. 成员函数的调用方法不知道是不是符合标准,不过估计移植性没什么问题。
2. static应该改为多线程安全的Singleton。
3. 没考虑异常安全。
4. 继承自两个有相同约束的concept的时候,产生调用不明确的问题。
可用重新声明约束的方法来解决。
另:
1. 关于非虚成员函数指针可以指向虚函数并正常调用的问题:
i) VC 如果指向的是没有基类的类的虚函数就可以。
ii) GCC 总是可以调用的。
2. VC6 不支持偏特化,不支持类模板参数的成员类模板。
// main.cpp
//
main.cpp
#include
<
stdio.h
>
#include
<
vector
>
#include
<
string
>
#include
"
shape.hpp
"
#include
"
concept.hpp
"

CONCEPT_MEMBER_FUNCTION(c_set_value, concept_base, set_value,
void
, (
int
Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value1, concept_base, set_value1,
void
, (
int
Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value2, concept_base, set_value2,
void
, (
int
Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value3, concept_base, set_value3,
void
, (
int
Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value4, concept_base, set_value4,
void
, (
int
Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_draw, concept_base, draw,
void
, (monitor device)
const
, (device));
CONCEPT_FUNCTION(g_set_value, concept_base, set_value,
void
, (ObjectType
&
t,
int
Value), (t, Value));
CONCEPT_FUNCTION(g_drawShape, concept_base, drawShape,
void
, (
const
ObjectType
&
t, monitor device), (t, device));
typedef concept_list
<
g_drawShape, c_draw, c_set_value, c_set_value1, c_set_value2, c_set_value3
>
Shape;


template
<>
struct
concept_map
<
Shape, Rectangle
>
...
{}
;


/**/
////
typedef auto_concept
<
Shape
>
auto_Shape;

void
DrawShapes(monitor device, std::vector
<
auto_Shape
>
const
&
g)

...
{
std::vector<auto_Shape>::const_iterator b(g.begin()), e(g.end());
for(; b != e; ++b)

...{
b->draw(device);
auto_Shape::drawShape(*b, device);
}
}

template
<
class
T
>
void
DrawShape(monitor device,
const
T
&
t)

...
{
if (0) concept<Shape> tmp = t; //static non-auto concept
t.draw(device);
}

int
main(
int
argc,
char
*
argv[])

...
{
auto_Shape as = Rectangle();
int sizeofShape = sizeof(Shape), sizeofconceptShape = sizeof(auto_Shape);
as.draw(stdout);
as.set_value(1);
as.draw(stdout);
as.set_value1(sizeofShape);
as.draw(stdout);
as.set_value2(sizeofconceptShape);
as.draw(stdout);
as.set_value3(1);
as.draw(stdout);

std::vector<auto_Shape> vg;
vg.push_back(Rectangle());
vg.push_back(Ellipse());
vg.push_back(vg[0]);
vg.push_back(vg[2]);
vg[2] = vg[0];
vg[3] = vg[1];
//vg.push_back(Triangle()); //错误,不符合Shape concept // OK in GCC
//vg.push_back(std::string("xxx")); //错误,不符合Shape concept
DrawShapes(stdout, vg);

Rectangle rect;
Ellipse elli;
EllipseChild ellichild;
DrawShape(stdout, rect);
//DrawShape(stdout, elli); //错误,不符合Shape static concept
//DrawShape(stdout, ellichild); //错误,不符合Shape static concept
ref_concept<Shape> ref_non_auto_Shape = rect;
ref_non_auto_Shape = rect;
//ref_non_auto_Shape = elli; //错误,不符合Shape non-auto concept
printf("rect.value = %d ", rect.value);
ref_non_auto_Shape.set_value(1);
printf("rect.value = %d ", rect.value);
ref_auto_concept<c_set_value>(rect).set_value(2);
ref_auto_concept<g_set_value> x(rect);
ref_auto_concept<g_set_value>::set_value(x, 2);
printf("rect.value = %d ", rect.value);

return 0;
}
// shape.hpp
//
shape.hpp
#include
<
stdio.h
>
typedef FILE
*
monitor;

struct
ShapeBase

...
{
int value;

ShapeBase() : value(0) ...{}
void set_value(int Value)

...{
value = Value;
}
void set_value1(int Value)

...{
value = Value;
}
void set_value2(int Value)

...{
value = Value;
}
void set_value3(int Value)

...{
value = Value;
}
void set_value4(int Value)

...{
value = Value;
}
}
;

struct
Rectangle :
public
ShapeBase

...
{
void draw(monitor device) const

...{
fprintf(device, "Rectangle.draw: %d ", value);
}
void draw() const

...{
printf("Rectangle.draw ?: %d ", value);
}
}
;

struct
Ellipse

...
{
int value;

Ellipse() : value(0) ...{}
void set_value(int Value)

...{
value = Value;
}
void set_value1(int Value)

...{
value = Value;
}
void set_value2(int Value)

...{
value = Value;
}
void set_value3(int Value)

...{
value = Value;
}
void set_value4(int Value)

...{
value = Value;
}
virtual void draw(monitor device) const

...{
fprintf(device, "Ellipse.draw: %d ", value);
}
}
;

struct
EllipseChild :
public
Ellipse

...
{
virtual void draw(monitor device) const

...{
fprintf(device, "EllipseChild.draw?: %d ", value);
}
}
;

struct
Triangle :
public
ShapeBase

...
{
virtual void draw(monitor device) const

...{
fprintf(device, "Triangle.draw virtual: %d ", value);
}
}
;

void
drawShape(
const
Rectangle
&
refShape, monitor device)

...
{
refShape.draw(device);
}

void
drawShape(
const
Ellipse
&
refShape, monitor device)

...
{
refShape.draw(device);
}

void
drawShape(
const
Triangle
&
refShape, monitor device)

...
{
refShape.draw(device);
}

template
<
class
T
>
void
set_value(T
&
refShape,
int
Value)

...
{
refShape.value = Value;
}
// concept.hpp
//
concept.hpp
#ifdef _MSC_VER
#define
MEMFUNCCAST(A) reinterpret_cast<A>
#else
#define
MEMFUNCCAST(A)
#endif

#define
CONCEPT_FUNCTION(CONCEPTNAME, BASE, FNAME, RTYPE, FTYPE, PARA)
struct
CONCEPTNAME

...
{
template <bool isvtable, class ObjectType>
struct table : public BASE::template table<isvtable, ObjectType>

...{
typedef typename get_type<RTYPE (*)FTYPE>::type function_type;
function_type p##FNAME;

table() : p##FNAME(&::FNAME) ...{}
};
template <class ObjectType>
struct table<false, ObjectType> : public BASE::template table<false, ObjectType>

...{

const void* CONCEPTNAME##_index() const ...{return this;}
static RTYPE FNAME FTYPE

...{
return (*t.ptable->p##FNAME)PARA;
}
};
}
;

#define
CONCEPT_MEMBER_FUNCTION(CONCEPTNAME, BASE, FNAME, RTYPE, FTYPE, PARA)
struct
CONCEPTNAME

...
{
template <bool isvtable, class ObjectType>
struct table : public BASE::template table<isvtable, ObjectType>

...{
typedef typename get_type<RTYPE (ObjectType::*)FTYPE>::type function_type;
function_type p##FNAME;

table() : p##FNAME(MEMFUNCCAST(function_type)(&ObjectType::FNAME)) ...{}
};
template <class ObjectType>
struct table<false, ObjectType> : public BASE::template table<false, ObjectType>

...{

const void* CONCEPTNAME##_index() const ...{return this;}
RTYPE FNAME FTYPE

...{
typedef typename ObjectType::TableType TableType;
typedef typename TableType::conceptType conceptType;
typedef concept<conceptType> concept_Type;
ObjectType* This = reinterpret_cast<ObjectType*>(
reinterpret_cast<size_t>(this) -
reinterpret_cast<size_t>(
reinterpret_cast<concept_Type*>(0)->CONCEPTNAME##_index()));
return (This->object_pointer->*This->ptable->p##FNAME)PARA;
}
};
}
;


template
<
class
T
>
struct
get_type
...
{typedef T type;}
;


struct
concept_object
...
{}
;

template
<
class
conceptT
=
int
,
class
T
=
int
>
struct
concept_map
...
{int t[2];}
;

struct
concept_base

...
{
template <bool isvtable, class ObjectType>
struct table

...{
};
}
;

template
<
class
First
=
concept_base,
class
Second
=
concept_base
>
struct
concept_pair

...
{
typedef concept_pair type;
template <bool isvtable = true, class ObjectType = concept_object>
struct table : public First::template table<isvtable, ObjectType>,
Second::template table<isvtable, ObjectType>

...{
};
}
;

template
<
class
SameType
>
struct
concept_pair
<
SameType, SameType
>

...
{
typedef concept_pair type;
template <bool isvtable = true, class ObjectType = concept_object>
struct table : public SameType::template table<isvtable, ObjectType>

...{
};
}
;

template
<
class
First
>
struct
concept_pair
<
First, concept_base
>

...
{
typedef First type;
}
;

template
<
class
Second
>
struct
concept_pair
<
concept_base, Second
>

...
{
typedef Second type;
}
;

template
<>
struct
concept_pair
<
concept_base, concept_base
>

...
{
typedef concept_base type;
}
;

template
<
class
C0
=
concept_base,
class
C1
=
concept_base,
class
C2
=
concept_base,
class
C3
=
concept_base,
class
C4
=
concept_base,
class
C5
=
concept_base,
class
C6
=
concept_base,
class
C7
=
concept_base,
class
C8
=
concept_base,
class
C9
=
concept_base,
class
C10
=
concept_base,
class
C11
=
concept_base,
class
C12
=
concept_base,
class
C13
=
concept_base,
class
C14
=
concept_base,
class
C15
=
concept_base,
class
C16
=
concept_base,
class
C17
=
concept_base,
class
C18
=
concept_base,
class
C19
=
concept_base
>
struct
concept_list

...
{
template <bool isvtable = true, class ObjectType = concept_object>
struct table : public
concept_pair< C0, typename concept_pair< C1, typename concept_pair< C2, typename concept_pair< C3, typename concept_pair< C4,
typename concept_pair< C5, typename concept_pair< C6, typename concept_pair< C7, typename concept_pair< C8, typename concept_pair< C9,
typename concept_pair<C10, typename concept_pair<C11, typename concept_pair<C12, typename concept_pair<C13, typename concept_pair<C14,
typename concept_pair<C15, typename concept_pair<C16, typename concept_pair<C17, typename concept_pair<C18, C19>
::type>::type>::type>::type>::type>::type>::type>::type>::type>::type>
::type>::type>::type>::type>::type>::type>::type>::type>::type
::template table<isvtable, ObjectType>

...{
};
}
;

template
<
class
TableT
>
struct
concept_class_base

...
{
typedef TableT TableType;

concept_object *object_pointer;
TableT *ptable;


operator const concept_object&() const ...{ return *object_pointer; }

operator concept_object&() ...{ return *object_pointer; }
}
;

template
<
class
conceptT,
class
T
=
concept_object
>
struct
concept_table :
public
conceptT::template table
<
true
, T
>

...
{
typedef conceptT conceptType;

typedef T* (*tcloneT)(const T *p);
typedef void (*tdeleteT)(T *p);
tcloneT pcloneT;
tdeleteT pdeleteT;
concept_table() :
pcloneT(reinterpret_cast<tcloneT>(&concept_table::cloneT)),

pdeleteT(reinterpret_cast<tdeleteT>(&concept_table::deleteT))...{}

static concept_table* vtable()

...{
static concept_table static_table;
return &static_table;
}
static T *cloneT(const T *p)

...{
return new T(*p);
}
static void deleteT(T *p)

...{
delete p;
}
}
;

template
<
class
conceptT
>
class
auto_concept;
template
<
class
conceptT
>
class
ref_concept;
template
<
class
conceptT
>
class
ref_auto_concept;

template
<
class
conceptT,
bool
isauto
=
false
,
bool
isref
=
false
>
class
concept :
public
concept_class_base
<
concept_table
<
conceptT
>
>
,
public
conceptT::template table
<
false
, concept_class_base
<
concept_table
<
conceptT
>
>
>

...
{
public:
using concept_class_base<concept_table<conceptT> >::ptable;
using concept_class_base<concept_table<conceptT> >::object_pointer;
typedef concept_table<conceptT> TableType;
private:
void init_with(concept_object* p, TableType* pTable)

...{
ptable = pTable;
if (isref)

...{
object_pointer = p;
}
else

...{
object_pointer = (*ptable->pcloneT)(p);
}
}
concept_object *cloneT() const

...{
return (*ptable->pcloneT)(object_pointer);
}
void deleteT()

...{
(*ptable->pdeleteT)(object_pointer);
}
public:
template <class T>
concept(const T& t)

...{
if (0) char static_assert[isauto || sizeof(concept_map<>) != sizeof(concept_map<conceptT, T>) ? 1 : -1];
typedef concept_table<conceptT, T> cTable;
init_with(const_cast<concept_object *>(reinterpret_cast<const concept_object *>(&t)),
(reinterpret_cast<TableType*>(cTable::vtable())));
}


concept(const concept& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const concept<conceptT, isauto, !isref>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const concept<conceptT, !isauto, isref>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const concept<conceptT, !isauto, !isref>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const auto_concept<conceptT>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const ref_concept<conceptT>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

concept(const ref_auto_concept<conceptT>& rhs) ...{ init_with(rhs.object_pointer, rhs.ptable); }

~concept()

...{
if (!isref) deleteT();
}

concept& operator = (const concept& rhs)

...{
concept(rhs).swap(*this);
return *this;
}

void swap(concept& rhs)

...{
concept_object *pointer0 = object_pointer;
TableType *ptable0 = ptable;
object_pointer = rhs.object_pointer;
ptable = rhs.ptable;
rhs.object_pointer = pointer0;
rhs.ptable = ptable0;
}
}
;

template
<
class
conceptT
>
class
auto_concept :
public
concept
<
conceptT,
true
,
false
>

...
{
public:
template <class T>

auto_concept(const T& t) : concept<conceptT, true, false>(t) ...{}
}
;

template
<
class
conceptT
>
class
ref_concept :
public
concept
<
conceptT,
false
,
true
>

...
{
public:
template <class T>

ref_concept(const T& t) : concept<conceptT, false, true>(t) ...{}
}
;

template
<
class
conceptT
>
class
ref_auto_concept :
public
concept
<
conceptT,
true
,
true
>

...
{
public:
template <class T>

ref_auto_concept(const T& t) : concept<conceptT, true, true>(t) ...{}
}
;