-----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

Reply via email to