11) 爲STL容器和數組提供統一的接口DataSet [原創,泛型編程,自由下載轉載,需註明出處]

源代碼可以在我的資源中去下載(包括用法測試的源代碼):
http://download.csdn.net/detail/tonny0832/7426991
只需要用VS建一個空的工程,然後引入我的測試頭文件即可。然後測試函數會在main函數之前運行,在控制檯窗口中可以看到輸出。


在一些產品上,對於數據塊,有些人喜歡用數組,比較典型的C程序員,有些人喜歡用STL容器,對於框架操作,我們通常希望存取這些對象能夠使用一套統一的接口去存取它,因爲從概念上講,它們無非就是一組數據的集合,我不關心存取它們方式的不同,只需要給我一個,存入一個數等。爲了滿足這些需求,下列源文件提供把C數組和STL容器做了統一的封裝,以提供一樣的接口。(沒有提供查入/刪除接口)


#ifndef __dataSet_h__
#define __dataSet_h__
#include "typeconvert.h"
#include "macroDef.h"
#include "typeTraits.h"
#include "libConfig.h"
/********************************************************************
Description : provide same package for classical array and STL container to same format .
Author : Shen.Xiaolong (Shen Tony) (2010-2013)
Mail : [email protected],  [email protected]
verified platform : VS2008
copyright:          : latest Version of The Code Project Open License (CPOL : http://www.codeproject.com/)
*********************************************************************/


/////////////////////////////////////////////////////// data set wrapper ////////////////////////////////////////////////////////////
//below macro is used to reduce string length in function interface
#define ET_(X)      UtilExt::GetValueTypeFromContainer<X>::type
#define ET(X)       typename ET_(X)                    //ET : element type of STL container or C Array
#define ETP_(X)     UtilExt::GetCPointer<X>::type    
#define ETP(X)      typename ETP_(X)            //ET : element type of STL container or C Array


namespace UtilExt
{
template<typename C,bool bStl=IsStlContainer<C>::value,bool bArr=isArray<C>::value> struct DataSet;
    template<typename Set_T,typename val_T,typename Pointer_T,typename size_T> 
    struct DataSetBase
    {
        typedef Set_T                                   PackageType;
        typedef typename AddRef<PackageType>::type      RefPackage_T;
        typedef size_T                                  size_type;


        typedef val_T                                   value_type;
        typedef Pointer_T                               iterator;
    };
    
    namespace CGetType
    {
        namespace DataSet
        {
            template<typename T,bool bStl=IsStlContainer<T>::value,bool bArr=isArray<T>::value> struct apply;
            template<typename T> struct apply<T,false,true> : public Type2Type<UtilExt::DataSet<typename AddRef<T>::type> >     {};
            template<typename T> struct apply<T,true,false> : public Type2Type<UtilExt::DataSet<typename RemoveRef<T>::type> >  {};
        }
    }


    template<typename T>    struct IsDataSet
    {
    private:
        template<typename U , typename P=NullType> struct CHasPackageType                                   : public FalseType{};
        template<typename U> struct CHasPackageType<U,typename sfinae_helper<typename U::PackageType>::type>: public TrueType {};


    public:
        enum {value = CHasPackageType<T>::value};
    };


    template<typename T, bool bIsDataSet=IsDataSet<T>::value> struct  GetCPointer;
    template<typename T> struct  GetCPointer<T,false> : public GetCPointer<typename CGetType::DataSet::apply<T>::type> {};
    template<typename T> struct  GetCPointer<T,true>  : public Type2Type<typename T::value_type*> {};


    template<typename T, bool bIsDataSet=IsDataSet<T>::value> struct  GetValueTypeFromContainer;
    template<typename T> struct  GetValueTypeFromContainer<T,false> : public GetValueTypeFromContainer<typename CGetType::DataSet::apply<T>::type> {};
    template<typename T> struct  GetValueTypeFromContainer<T,true>  : public Type2Type<typename T::value_type> {};


////////////////////////////////stl container ///////////////////////////////////////////////////////////////////////////
    template<typename Stl_T>    struct DataSet<Stl_T,true,false> 
    : public DataSetBase<Stl_T,
        typename Evl_If_T<IsConst<Stl_T>,AddConst<typename Stl_T::value_type>,Type2Type<typename Stl_T::value_type> >::type::type,
        typename Evl_If_T<IsConst<Stl_T>,typename Stl_T::const_iterator,typename Stl_T::iterator>::type,
        typename Stl_T::size_type> 
{
explicit DataSet(RefPackage_T obj)
: m_obj(obj)
{ }


iterator begin()
{
return m_obj.begin();
}


iterator end()
{
return m_obj.end();
}


iterator head()
{
return size()>0 ? begin() : end();
}


iterator tail()
{
            iterator pTmp = end();
            return size()>0 ? --pTmp : pTmp;
//return size()>0 ? --end() : end();   //some special stl container doesn't support this usage
}


value_type& front()
{
            ChkExceptionX(size()>0);
return m_obj.front();
}


value_type& back()
        {
            ChkExceptionX(size()>0);
            return m_obj.back();
}


        template<typename T>
        static value_type& At(T& obj, size_type i)
        {
            Assertb(i < obj.size());
            iterator it=obj.begin();
            for (size_type cnt=0; cnt<i; cnt++ , ++it);
            Assertb(it!=obj.end());
            return *(it);
        }


        static value_type& At(stlVector<value_type>& obj, size_type i)
        {         
            Assertb(i < obj.size());
            return obj[i];
        }


        value_type& operator[](size_type i)
        { 
            return At(m_obj,i);
        }


size_type size() const
{
return m_obj.size();
}


void clear()
{
m_obj.clear();
}


void push_back(value_type const& val)
{
m_obj.push_back(val);
}

        operator PackageType&()
{
return m_obj;
}        


RefPackage_T    m_obj;
};


template<typename Stl_T>
    DataSet<Stl_T> makeDataSet(Stl_T& stlArr,SFINAE(IsStlContainer<Stl_T>::value))
{
return DataSet<Stl_T>(stlArr);
}


template<typename Stl_T>
DataSet<Stl_T> makeResult(Stl_T& rResult,SFINAE(IsStlContainer<Stl_T>::value))
{
return makeDataSet(rResult);
}


////////////////////////////////class array ///////////////////////////////////////////////////////////////////////////
template<typename T> struct ArrValTypeHelper;
    template<typename S,unsigned int LEN> struct ArrValTypeHelper<S[LEN]>    : public Type2Type<S> {};
    template<typename S,unsigned int LEN> struct ArrValTypeHelper<S(&)[LEN]> : public Type2Type<S> {};


    template<typename Arr_T>   struct DataSet<Arr_T,false,true> 
    : public DataSetBase<Arr_T,
        typename ArrValTypeHelper<Arr_T>::type,
        typename ArrValTypeHelper<Arr_T>::type*,
        unsigned int> 
{
        enum{array_len=ArraySize<Arr_T>::value};


explicit DataSet(RefPackage_T obj,size_type iSize=0)
: m_obj(obj)
, m_iSize(iSize)
{
            ChkExceptionX(m_iSize<=array_len);
}


iterator begin()
{
return m_iSize>0 ? &m_obj[0] : NULL;
}


iterator end()
{
return m_iSize>0 ? &m_obj[m_iSize] : NULL ;
}


iterator head()
{
return begin();
}


iterator tail()
{
return m_iSize>0 ? &m_obj[m_iSize-1] : NULL ;
}


value_type& front()
{
ChkExceptionX(size()>0);
return *head();
}


value_type& back()
{
ChkExceptionX(size()>0);
return *tail();
}


void push_back(value_type const& val)
{
            if (size()<array_len)
            {
                new (&m_obj[m_iSize]) value_type(val);
                m_iSize++;
            }
            else
            {
   ChkExceptionX(size()<array_len);
            }
}


        value_type& operator[](size_type i)
        { 
            Assertb(i<array_len);
            return m_obj[i];
        }


size_type size() const
{
return m_iSize;



void clear()
{
m_iSize = 0;
}


        /*  
        below operator cause ambiguity, e.g. for rArr[2] , it could be
           S &UtilExt::DataSet<S(&)[LEN]>::operator [](UtilExt::DataSet<S(&)[LEN]>::size_type)
        or built-in C++ operator[](S [LEN], int)
        can un-comment-out below operation and compile to see compile error
        it is say : only one is available in value_type& operator[](size_type i) / operator PackageType&()
        because we need to assert index, so we have to discard operator PackageType&() and keep value_type& operator[](size_type i)
        */
        /*/
operator PackageType&()
{
return m_obj;
}
        //*/

size_type           m_iSize;
        RefPackage_T        m_obj;
};


template<typename S,unsigned int LEN>
DataSet<S (&)[LEN]> makeDataSet(S (&obj)[LEN],unsigned int iSize=LEN)
{    
return DataSet<S (&)[LEN]>(obj,iSize);
};


template<typename S,unsigned int LEN>
DataSet<S(&)[LEN]> makeResult(S(&rResult)[LEN],unsigned int iSize=0)
{
return makeDataSet(rResult,iSize);
}
}


#endif // dataSet_h__

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章