-----Original Message-----
From: Vladimir Prus [mailto:[EMAIL PROTECTED]
Sent: Monday, March 24, 2003 10:25 AM
To: Boost mailing list
Subject: Re: [boost] boost::any feature request
[]
P.S. And, BTW, it would be great to see the complete code that you
propose (or
a diff to CVS HEAD).
Here are the sources I played with. It's far from perfect, but I think
the basic idea is clear.
The TailoredAny<> class has the prototype:
<code>
template<class NewStrategy_ = Loki::EmptyType, class TypeInfoStrategy_ =
RttiTypeInfoStrategy>
class TailoredAny;
</code>
So, it can be parametrized with the type identification strategy, not
the memory allocation strategy only.
And here are the Intel VTune results (see the sources for details):
Creation Assignment
struct 13383 27358
boost::any 3846 331870
TailoredAny<> 9151 310717
TailoredAny<Loki::SmallObject> 3855 110022
If we throw away the type identification strategy and leave it hardcoded
as in the original boost::any the result of the TailoredAny<> will be
better.
////////////////////////////////////////////////////////////////////////////////////////////////////
// TailoredAny.h
#pragma once
#include <algorithm>
#include <Loki/EmptyType.h>
#include <Loki/TypeInfo.h>
struct RttiTypeInfoStrategy
{
typedef Loki::TypeInfo TypeInfo;
template<typename T>
static TypeInfo Identify() { return typeid(T); }
template<typename T>
static TypeInfo Identify(const T& t) { return typeid(t); }
};
template<class NewStrategy_ = Loki::EmptyType, class TypeInfoStrategy_ =
RttiTypeInfoStrategy>
class TailoredAny
{
public:
typedef TypeInfoStrategy_ TypeInfoStrategy;
typedef typename TypeInfoStrategy_::TypeInfo TypeInfo;
TailoredAny()
: content_(0)
{}
template<class ValueType_>
TailoredAny(const ValueType_& value)
: content_(new Holder_<ValueType_>(value))
{}
TailoredAny(const TailoredAny& other)
: content_(other.content_ ? other.content_->Clone() : 0)
{}
~TailoredAny() { delete content_; }
template<class ValueType_>
TailoredAny& operator=(const ValueType_& value)
{
TailoredAny(value).Swap(*this);
return *this;
}
TailoredAny& operator=(const TailoredAny& other)
{
TailoredAny(other).Swap(*this);
return *this;
}
void Swap(TailoredAny& other)
{
std::swap(content_, other.content_);
}
bool Empty() const { return !content_; }
TypeInfo Type() const
{
return content_ ? content->Type() :
TypeInfoStrategy_::Identify<void>();
}
private:
struct PlaceHolder_ : NewStrategy_
{
virtual TypeInfo Type() const = 0;
virtual PlaceHolder_* Clone() const = 0;
virtual ~PlaceHolder_() {}
};
template<class ValueType_>
struct Holder_ : PlaceHolder_
{
Holder_(const ValueType_& value)
: held_(value)
{}
TypeInfo Type() const
{
return TypeInfoStrategy_::Identify(held_);;
}
PlaceHolder_* Clone() const
{
return new Holder_(held_);
}
ValueType_ held_;
};
template<class ValueType_, class S1_, class S2_>
friend ValueType_* TailoredAnyCast(TailoredAny<S1_, S2_>*);
PlaceHolder_* content_;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class ValueType_, class S1_, class S2_>
ValueType_* TailoredAnyCast(TailoredAny<S1_, S2_>* operand)
{
typedef TailoredAny<S1_, S2_>::TypeInfoStrategy TypeInfoStrategy;
return operand && operand->Type() == TypeInfoStrategy::Identify<ValueType_>()
? &static_cast<TailoredAny<S1_,
S2_>::Holder_<ValueType_>*>(operand->content_)->held_
: 0;
}
template<class ValueType_, class S1_, class S2_>
const ValueType_* TailoredAnyCast(const TailoredAny<S1_, S2_>* operand)
{
return TailoredAnyCast<ValueType_, S1_>(const_cast<TailoredAny<S1_,
S2_>*>(operand));
}
template<class ValueType_, class S1_, class S2_>
ValueType_ TailoredAnyCast(const TailoredAny<S1_, S2_>& operand)
{
const ValueType_* result = TailoredAnyCast<ValueType_>(&operand);
if(!result)
throw std::bad_cast();
return *result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// play_with_any.cpp : Defines the entry point for the console application.
//
#include <tchar.h>
#include <vector>
#include <string>
#include <boost/any.hpp>
#include <Loki/SmallObj.h>
#include <Loki/TypeManip.h>
#include "TailoredAny.h"
typedef std::basic_string<TCHAR> tstring;
////////////////////////////////////////////////////////////////////////////////////////////////////
// 'typical' properties structure
template<class Variant_>
struct Properties;
template<>
struct Properties<void>
{
bool bool1;
int int1;
int int2;
int int3;
int int4;
double double1;
tstring string1;
};
template<class Variant_>
struct Properties
{
Variant_ bool1;
Variant_ int1;
Variant_ int2;
Variant_ int3;
Variant_ int4;
Variant_ double1;
Variant_ string1;
};
const tstring text(_T("Some new string property"));
#define ASSIGN_PROPERTIES(p) \
p.bool1 = true;\
p.int1 = 1;\
p.int1 = 2;\
p.int3 = 3;\
p.int4 = 4;\
p.double1 = 3.14;\
p.string1 = text;
////////////////////////////////////////////////////////////////////////////////////////////////////
// custom type info strategy
template<typename T> struct TypeInfoTraits { enum { type = -1 }; };
template<> struct TypeInfoTraits<void> { enum { type = 0 }; };
template<> struct TypeInfoTraits<bool> { enum { type = 1 }; };
template<> struct TypeInfoTraits<int> { enum { type = 2 }; };
template<> struct TypeInfoTraits<double> { enum { type = 3 }; };
template<> struct TypeInfoTraits<tstring> { enum { type = 4 }; };
class CustomTypeInfoStrategy
{
static int TypeImpl(Loki::Int2Type<-1>);
template<int N> static int TypeImpl(Loki::Int2Type<N>) { return N; }
public:
typedef int TypeInfo;
template<typename T>
static TypeInfo Type()
{
return TypeImpl(Loki::Int2Type<TypeInfoTraits<T>::type>());
}
template<typename T>
static TypeInfo Type(const T&) { return Type<T>(); }
};
////////////////////////////////////////////////////////////////////////////////////////////////////
typedef std::vector<Properties<void> > SIMPLE_VEC;
typedef std::vector<Properties<boost::any> > BOOST_ANY_VEC;
// must be the same as with boost::any (1)
typedef std::vector<Properties<TailoredAny<> > > TAILORED_ANY_VEC;
// using with Loki::SmallObject for allocation (2)
typedef std::vector<Properties<TailoredAny<Loki::SmallObject<> > > >
TAILORED_ANY_VEC_M;
const size_t N = 0x10000;
////////////////////////////////////////////////////////////////////////////////////////////////////
// creation
void CreateS(SIMPLE_VEC& v)
{
SIMPLE_VEC(N).swap(v);
}
void CreateA(BOOST_ANY_VEC& v)
{
BOOST_ANY_VEC(N).swap(v);
}
void CreateT(TAILORED_ANY_VEC& v)
{
TAILORED_ANY_VEC(N).swap(v);
}
void CreateTm(TAILORED_ANY_VEC_M& v)
{
TAILORED_ANY_VEC_M(N).swap(v);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// assignment
void AssignS(SIMPLE_VEC& v)
{
for(size_t i = v.size(); i--;)
{
SIMPLE_VEC::value_type& p = v[i];
ASSIGN_PROPERTIES(p)
}
}
void AssignA(BOOST_ANY_VEC& v)
{
for(size_t i = v.size(); i--;)
{
BOOST_ANY_VEC::value_type& p = v[i];
ASSIGN_PROPERTIES(p)
}
}
void AssignT(TAILORED_ANY_VEC& v)
{
for(size_t i = v.size(); i--;)
{
TAILORED_ANY_VEC::value_type& p = v[i];
ASSIGN_PROPERTIES(p)
}
}
void AssignTm(TAILORED_ANY_VEC_M& v)
{
for(size_t i = v.size(); i--;)
{
TAILORED_ANY_VEC_M::value_type& p = v[i];
ASSIGN_PROPERTIES(p)
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
SIMPLE_VEC v1(0);
BOOST_ANY_VEC v2(0);
TAILORED_ANY_VEC v3(0);
TAILORED_ANY_VEC_M v4(0);
CreateS(v1);
CreateA(v2);
CreateT(v3);
CreateTm(v4);
AssignS(v1);
AssignA(v2);
AssignT(v3);
AssignTm(v4);
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost