Runtime Concept 的模拟(5)

来源:互联网 发布:淘宝发布 编辑:程序博客网 时间:2024/05/19 23:28

Runtime Concept 的模拟(5)
简化使用方法!
用链式的单继承解决多继承方法的调用不明确的问题。
支持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. 没考虑异常安全。

另:
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, set_value, 
void, (int Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value1, set_value1, 
void, (int Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value2, set_value2, 
void, (int Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value3, set_value3, 
void, (int Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_set_value4, set_value4, 
void, (int Value), (Value));
CONCEPT_MEMBER_FUNCTION(c_draw, draw, 
void, (monitor device) const, (device));
CONCEPT_FUNCTION(g_set_value, set_value, 
void, (ObjectType &t, int Value), (t, Value));
CONCEPT_FUNCTION(g_drawShape, 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, 
                     c_set_value4
> 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, FNAME, RTYPE, FTYPE, PARA) 
struct CONCEPTNAME 

    template 
<class BaseFrom = concept_base, bool isvtable = trueclass ObjectType = concept_object> 
    
struct table : public concept_bind_with<typename BaseFrom::Base, typename BaseFrom::DeriveFrom, isvtable, ObjectType>::type 
    

        typedef CONCEPTNAME Base; 
        typedef BaseFrom DeriveFrom; 
        typedef typename get_type
<RTYPE (*)FTYPE>::type function_type; 
        function_type p##FNAME; 
        table() : p##FNAME(
&::FNAME) {} 
    }

    template 
<class BaseFrom, class ObjectType> 
    
struct table<BaseFrom, false, ObjectType> : public concept_bind_with<typename BaseFrom::Base, typename BaseFrom::DeriveFrom, false, ObjectType>::type 
    

        typedef CONCEPTNAME Base; 
        typedef BaseFrom DeriveFrom; 
        
const void* CONCEPTNAME##_index() const {return this;} 
        
static RTYPE FNAME FTYPE 
        

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

}
;

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

    template 
<class BaseFrom = concept_base, bool isvtable = trueclass ObjectType = concept_object> 
    
struct table : public concept_bind_with<typename BaseFrom::Base, typename BaseFrom::DeriveFrom, isvtable, ObjectType>::type 
    

        typedef CONCEPTNAME Base; 
        typedef BaseFrom DeriveFrom; 
        typedef typename get_type
<RTYPE (ObjectType::*)FTYPE>::type function_type; 
        function_type p##FNAME; 
        table() : p##FNAME(MEMFUNCCAST(function_type)(
&ObjectType::FNAME)) {} 
    }

    template 
<class BaseFrom, class ObjectType> 
    
struct table<BaseFrom, false, ObjectType> : public concept_bind_with<typename BaseFrom::Base, typename BaseFrom::DeriveFrom, false, ObjectType>::type 
    

        typedef CONCEPTNAME Base; 
        typedef BaseFrom DeriveFrom; 
        
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_base;
struct concept_object{};
template 
<class conceptT = intclass T = int> struct concept_map {int t[2];};

template 
<class conceptT, class BaseFrom = concept_base, bool isvtable = trueclass ObjectType = concept_object>
struct concept_bind_with
{
    typedef typename conceptT::template table
<BaseFrom, isvtable, ObjectType> type;
}
;

struct concept_base
{
    typedef concept_base Base;
    typedef concept_base DeriveFrom;
    template 
<class BaseFrom = concept_base, bool isvtable = trueclass ObjectType = concept_object>
    
struct table : public concept_bind_with<typename BaseFrom::Base, typename BaseFrom::DeriveFrom, isvtable, ObjectType>::type
    
{
        typedef concept_base Base;
        typedef BaseFrom DeriveFrom;
    }
;
    template 
<bool isvtable, class ObjectType>
    
struct table<concept_base, isvtable, ObjectType>
    
{
        typedef concept_base Base;
        typedef concept_base DeriveFrom;
    }
;
}
;

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 
<class BaseFrom = concept_base, bool isvtable = trueclass T = concept_object>
    
struct table : public
                 concept_bind_with
< C0,typename concept_bind_with< C1,typename concept_bind_with< C2,typename concept_bind_with< C3,typename concept_bind_with< C4,
        typename concept_bind_with
< C5,typename concept_bind_with< C6,typename concept_bind_with< C7,typename concept_bind_with< C8,typename concept_bind_with< C9,
        typename concept_bind_with
<C10,typename concept_bind_with<C11,typename concept_bind_with<C12,typename concept_bind_with<C13,typename concept_bind_with<C14,
        typename concept_bind_with
<C15,typename concept_bind_with<C16,typename concept_bind_with<C17,typename concept_bind_with<C18,typename concept_bind_with<C19,
        BaseFrom
        
>::type>::type>::type>::type>::type>::type>::type>::type>::type>::type
        
>::type>::type>::type>::type>::type>::type>::type>::type>::type, isvtable, T>::type
    
{
        typedef concept_list Base;
        typedef BaseFrom DeriveFrom;
    }
;
}
;

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 concept_bind_with<conceptT, concept_base, true, T>::type
{
    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 = falsebool isref = false>
class concept : 
    
public concept_class_base<concept_table<conceptT> >
    
public concept_bind_with<conceptT, concept_base, false, concept_class_base<concept_table<conceptT> > >::type
{
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 (0char 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, truefalse>
{
public:
    template 
<class T>
    auto_concept(
const T& t) : concept<conceptT, truefalse>(t) {}
}
;

template 
<class conceptT>
class ref_concept : public concept<conceptT, falsetrue>
{
public:
    template 
<class T>
    ref_concept(
const T& t) : concept<conceptT, falsetrue>(t) {}
}
;

template 
<class conceptT>
class ref_auto_concept : public concept<conceptT, truetrue>
{
public:
    template 
<class T>
    ref_auto_concept(
const T& t) : concept<conceptT, truetrue>(t) {}
}
;
原创粉丝点击