📄 variant_cc.h
字号:
// (C) 2000, Fernando Luis Cacciola Carballal.
//
// This material is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// Permission to use or copy this software for any purpose is hereby granted
// without fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is granted,
// provided the above notices are retained, and a notice that the code was
// modified is included with the above copyright notice.
//
// You are welcome to contact the author at: fcacciola@fibertel.com.ar
#ifndef VARIANT_CC_H
#define VARIANT_CC_H
#include "DB_Base.h"
#include "Callback.h"
#include "VariantException.h"
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
BEGIN_DTL_NAMESPACE
//
// NOTE: The following conditional compilation macros will change the interface
// for variant_cc_t.
//
// NO_EXPLICIT_MEMBER_TPL_INSTANTIATION :
//
// Some compilers fail to explicitely instantiate member template functions:
// They won't compile: int n = my_variant.get<int>()
// One solution is to add an extra dummy argument to help name lookup.
//
// If NO_EXPLICIT_MEMBER_TPL_INSTANTIATION is defined, some methods will have this
// extra argument. This extra argument is not used so it is declared as a const* so
// you can pass (T cosnt*)NULL.
//
#define NO_EXPLICIT_MEMBER_TPL_INSTANTIATION
#ifdef _MSC_VER
#pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' (performance warning)
#endif
// Class variant_cc_t
// This is a variation of variant_cc_t.
// It implements a 'copy on copy' scheme: that is,
// each time a variant_cc_t is copied it internal
// data is copied too.
// This avoids the shared implementation at the cost of
// copying the value held.
//
// Those portions of this code which differ from variant_cc_t
// have a comment.
//
// Mar 2000, Fernando Luis Cacciola Carballal.
//
// 26/09/2000 FLC (T v) arguments changed to (T const& v).
// 26/09/2000 FLC std:: added to throw expresion.
// 27/09/2000 FLC MSVC changes.
// * NO_EXPLICIT_MEMBER_TPL_INSTANTIATION conditional compilation added.
// * One of the 'is_type' methods was renamed to 'is_type_as'
// to avoid overload resolution problems.
class variant_cc_t
{
private:
// Don't allow default constructor -- too dangerous
// Too easy to end up with functions pointing into NULL objects
// Let the compiler help us at compile time by forbidding default construction
variant_cc_t() : data ( NULL ) {}
public :
template<typename T> variant_cc_t ( T const& v )
: data ( new Impl<T>(v) )
{}
// * Copy the internal data instead of sharing it.
variant_cc_t( const variant_cc_t & rhs )
: data ( rhs.data != NULL ? rhs.data->clone()
: NULL
)
{}
// No need to test for concurrent users.
~variant_cc_t()
{ delete data ; }
void swap(variant_cc_t &other)
{
std::swap(data, other.data);
}
// * Copy the internal data instead of sharing it.
variant_cc_t& operator = ( const variant_cc_t& rhs )
{
if (this != &rhs)
{
variant_cc_t tmp(rhs);
swap(tmp);
}
return * this ;
}
template<typename T> operator T () const
{ return CastFromBase<T>( data )->data ; }
#ifdef NO_EXPLICIT_MEMBER_TPL_INSTANTIATION
template<typename T> const T & get( T const* dmy =NULL ) const
{ return CastFromBase( data , dmy )->data ; }
#else
template<typename T> const T & get() const
{ return CastFromBase<T>( data )->data ; }
#endif
#ifdef NO_EXPLICIT_MEMBER_TPL_INSTANTIATION
template<typename T> bool is_type() const
#else
template<typename T> bool is_type() const
#endif
{ return typeid(*data)==typeid(Impl<T>); }
template<typename T> bool is_type_as(T const& v) const
{ return typeid(*data)==typeid(v); }
template<typename T> bool is_type_as(T const* v) const
{ return typeid(*data)==typeid(v); }
// need versions for 0,1,2,3,4 params with or without return values
// *** register a functor for the object ***
// first, we need versions for non-const member functions
template<class T> void AddCBFunctor0(const int &funcName,
void (T::*func) (void))
{
CBFunctor((CBFunctor0 *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1> void AddCBFunctor1(const int &funcName,
void (T::*func) (P1))
{
CBFunctor((CBFunctor1<P1> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2> void AddCBFunctor2(const int &funcName,
void (T::*func) (P1, P2))
{
CBFunctor((CBFunctor2<P1, P2> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3>
void AddCBFunctor3(const int &funcName, void (T::*func) (P1, P2, P3))
{
CBFunctor((CBFunctor3<P1, P2, P3> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class P4> void
AddCBFunctor4(const int &funcName, void (T::*func) (P1, P2, P3, P4))
{
CBFunctor((CBFunctor4<P1, P2, P3, P4> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class RT> void AddCBFunctor0_w_ret(const int &funcName,
RT (T::*func) (void))
{
CBFunctor((CBFunctor0wRet<RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class RT> void AddCBFunctor1_w_ret(const int &funcName,
RT (T::*func) (P1))
{
CBFunctor((CBFunctor1wRet<P1, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class RT> void AddCBFunctor2_w_ret(const int &funcName,
RT (T::*func) (P1, P2))
{
CBFunctor((CBFunctor2wRet<P1, P2, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class RT>
void AddCBFunctor3_w_ret(const int &funcName,
RT (T::*func) (P1, P2, P3))
{
CBFunctor((CBFunctor3wRet<P1, P2, P3, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class P4, class RT>
void AddCBFunctor4_w_ret(const int &funcName,
RT (T::*func) (P1, P2, P3, P4))
{
CBFunctor((CBFunctor4wRet<P1, P2, P3, P4, RT> *)NULL, (T *) NULL, funcName, func);
}
// also need versions for const member functions
template<class T> void AddCBFunctor0(const int &funcName,
void (T::*func) (void) const)
{
CBFunctor((CBFunctor0 *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1> void AddCBFunctor1(const int &funcName,
void (T::*func) (P1) const)
{
CBFunctor((CBFunctor1<P1> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2> void AddCBFunctor2(const int &funcName,
void (T::*func) (P1, P2) const)
{
CBFunctor((CBFunctor2<P1, P2> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3>
void AddCBFunctor3(const int &funcName, void (T::*func) (P1, P2, P3) const)
{
CBFunctor((CBFunctor3<P1, P2, P3> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class P4> void
AddCBFunctor4(const int &funcName, void (T::*func) (P1, P2, P3, P4) const)
{
CBFunctor((CBFunctor4<P1, P2, P3, P4> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class RT> void AddCBFunctor0_w_ret(const int &funcName,
RT (T::*func) (void) const)
{
CBFunctor((CBFunctor0wRet<RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class RT> void AddCBFunctor1_w_ret(const int &funcName,
RT (T::*func) (P1) const)
{
CBFunctor((CBFunctor1wRet<P1, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class RT> void AddCBFunctor2_w_ret(const int &funcName,
RT (T::*func) (P1, P2) const)
{
CBFunctor((CBFunctor2wRet<P1, P2, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class RT>
void AddCBFunctor3_w_ret(const int &funcName,
RT (T::*func) (P1, P2, P3) const)
{
CBFunctor((CBFunctor3wRet<P1, P2, P3, RT> *)NULL, (T *) NULL, funcName, func);
}
template<class T, class P1, class P2, class P3, class P4, class RT>
void AddCBFunctor4_w_ret(const int &funcName,
RT (T::*func) (P1, P2, P3, P4) const)
{
CBFunctor((CBFunctor4wRet<P1, P2, P3, P4, RT> *)NULL, (T *) NULL, funcName, func);
}
// get a pointer to the FunctorBase for this variant
CBFunctorBase *GetFunctorBase(const int &funcName) const
{
return data->GetFunctorBase(funcName);
}
private :
// helper function that rips apart the actual types and records the
// functor under the funcName passed in
template <class T, class CBFunctorType, class Func>
void CBFunctor(CBFunctorType *pcbt, T *dummy, const int &funcName, Func func) {
Impl<T>* p = dynamic_cast<Impl<T>*> ( data ) ;
if (p == NULL)
throw VariantException("variant_cc_t::CBFunctor()",
"dynamic cast failed: function is not a member of this object");
CBFunctorBase *pFbase = new CBFunctorType(
makeFunctor((CBFunctorType *) 0, p->data , func)
);
data->AddCBFunctor(funcName, pFbase);
}
// This version has a clone() method so copies
// of particular Impl<> can be obtained.
struct ImplBase
{
typedef pair<int, CBFunctorBase *> CallbackPair;
typedef vector<CallbackPair> MethodList;
MethodList methods; // vector of callback id, func
ImplBase() : methods() {}
// need to delete the CBFunctorBase objects
virtual ~ImplBase ()
{
for (MethodList::iterator it = methods.begin(); it != methods.end(); it++)
{
CallbackPair &pr = *it;
delete pr.second;
pr.second = NULL;
}
}
virtual ImplBase* clone() const = 0 ;
MethodList::iterator find_func(const int &funcName) const {
ImplBase *this_ptr = const_cast<ImplBase *>(this);
MethodList::iterator it_end = this_ptr->methods.end();
MethodList::iterator it = this_ptr->methods.begin();
for ( ; it != it_end; ++it)
{
if ((*it).first == funcName)
break;
}
if (it == it_end)
throw VariantException("variant_cc_t::ImplBase::find_func()", "No such method registered!");
return it;
}
// gets a pointer to FunctorBase for the funcName passed in
// returns NULL if none found
CBFunctorBase *GetFunctorBase(const int &funcName) const
{
// finds and returns the CBFunctorBase * with the given funcName
MethodList::const_iterator it;
try
{
it = find_func(funcName);
return (*it).second;
}
catch (...)
{
}
return NULL; // suppress warnings
}
// registers a functor with the given name in a typeless manner
void AddCBFunctor(const int &funcName, CBFunctorBase *pFbase)
{
methods.push_back(CallbackPair(funcName, pFbase));
}
} ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -