Benjamin Kaufmann's port
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@87 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
ca94249f94
commit
10c21af076
7 changed files with 348 additions and 201 deletions
|
@ -13,7 +13,8 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: Oct 24, 2002
|
// Last update: Dec 08, 2002
|
||||||
|
|
||||||
|
|
||||||
#ifndef HIERARCHYGENERATORS_INC_
|
#ifndef HIERARCHYGENERATORS_INC_
|
||||||
#define HIERARCHYGENERATORS_INC_
|
#define HIERARCHYGENERATORS_INC_
|
||||||
|
@ -68,15 +69,40 @@ namespace Loki
|
||||||
//
|
//
|
||||||
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
|
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
|
||||||
// (http://lists.boost.org/MailArchives/boost/msg20915.php)
|
// (http://lists.boost.org/MailArchives/boost/msg20915.php)
|
||||||
|
//
|
||||||
|
// Update:
|
||||||
|
// -------
|
||||||
|
// The first version of GenScatterHierarchy did not work with typelists
|
||||||
|
// containing equal types. The MSVC 6.0 erroneously complains about
|
||||||
|
// inaccessible base-classes (error C2584).
|
||||||
|
// This new version adds Dummy-classes to the left branch of the generated
|
||||||
|
// hierarchy to workaround this VC-Bug.
|
||||||
|
// It creates hierarchies like this:
|
||||||
|
//
|
||||||
|
// Holder<int> NullType
|
||||||
|
// \ /
|
||||||
|
//Holder<int> GenScatter<int> GenScatter<NullType>
|
||||||
|
// \ \ /
|
||||||
|
//VC_InaccessibleBase InheritFromTo
|
||||||
|
// \ |
|
||||||
|
//GenScatter<int> GenScatter<TYPELIST_1(int)>
|
||||||
|
// \ /
|
||||||
|
// InheritFromTo
|
||||||
|
// |
|
||||||
|
// |
|
||||||
|
//GenScatter<TYPELIST_2(int, int)>
|
||||||
|
//
|
||||||
|
// Of course this version of GenScatterHierarchy generates a lot more
|
||||||
|
// classes (5*n) than Alexandrescu's original implementation (3*n)
|
||||||
|
//
|
||||||
|
|
||||||
template <class TList, class Unit> class GenScatterHierarchy;
|
template <class TList, class Unit> class GenScatterHierarchy;
|
||||||
|
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
class InheritFromTwo : public T, public U
|
struct InheritFromTwo : public T, public U
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int tag>
|
template <int tag>
|
||||||
|
@ -90,16 +116,34 @@ namespace Private
|
||||||
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
||||||
{
|
{
|
||||||
typedef
|
typedef
|
||||||
InheritFromTwo < GenScatterHierarchy<typename T::Head,
|
InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
|
||||||
MetaFunctionWrapper>,
|
MetaFunctionWrapper>, typename T::Tail>,
|
||||||
GenScatterHierarchy<typename T::Tail,
|
GenScatterHierarchy<typename T::Tail,
|
||||||
MetaFunctionWrapper>
|
MetaFunctionWrapper>
|
||||||
> type;
|
> type;
|
||||||
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
|
typedef VC_InaccessibleBase<GenScatterHierarchy<typename T::Head, MetaFunctionWrapper>,typename T::Tail> LeftBase;
|
||||||
typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase;
|
typedef GenScatterHierarchy<typename T::Tail, MetaFunctionWrapper> RightBase;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Specialization for a typelist with only one element
|
||||||
|
template <>
|
||||||
|
struct GenScatterImpl<TL::Private::AtomList_ID>
|
||||||
|
{
|
||||||
|
template <class T, class MetaFunctionWrapper>
|
||||||
|
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
||||||
|
{
|
||||||
|
// for the last Holder-class no dummy class is needed.
|
||||||
|
typedef
|
||||||
|
InheritFromTwo < GenScatterHierarchy<typename T::Head,
|
||||||
|
MetaFunctionWrapper>,
|
||||||
|
GenScatterHierarchy<NullType,
|
||||||
|
MetaFunctionWrapper>
|
||||||
|
> type;
|
||||||
|
typedef GenScatterHierarchy<typename T::Head, MetaFunctionWrapper> LeftBase;
|
||||||
|
typedef GenScatterHierarchy<NullType, MetaFunctionWrapper> RightBase;
|
||||||
|
};
|
||||||
|
};
|
||||||
// Specialization for a single type
|
// Specialization for a single type
|
||||||
template <>
|
template <>
|
||||||
struct GenScatterImpl<TL::Private::NoneList_ID>
|
struct GenScatterImpl<TL::Private::NoneList_ID>
|
||||||
|
@ -111,7 +155,9 @@ namespace Private
|
||||||
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
|
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
|
||||||
typedef type LeftBase;
|
typedef type LeftBase;
|
||||||
typedef EmptyType RightBase;
|
typedef EmptyType RightBase;
|
||||||
|
//typedef AtomicType::THIS_SELECTED bla;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specialization for NullType
|
// Specialization for NullType
|
||||||
|
@ -131,10 +177,7 @@ namespace Private
|
||||||
template <class T, class Unit>
|
template <class T, class Unit>
|
||||||
class GenScatterHierarchy : public Private::GenScatterImpl
|
class GenScatterHierarchy : public Private::GenScatterImpl
|
||||||
<
|
<
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
|
IS_TYPELIST(T)::type_id
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
|
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
|
|
||||||
TL::Private::NoneList_ID
|
|
||||||
>::template In<T, Unit>::type
|
>::template In<T, Unit>::type
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -142,20 +185,14 @@ namespace Private
|
||||||
<
|
<
|
||||||
TL::Private::IsTypelist<T>::value, T, void
|
TL::Private::IsTypelist<T>::value, T, void
|
||||||
>::Result TList;
|
>::Result TList;
|
||||||
typedef typename Private::GenScatterImpl
|
|
||||||
<
|
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
|
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
|
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
|
|
||||||
TL::Private::NoneList_ID
|
|
||||||
>::template In<T, Unit>::LeftBase LeftBase;
|
|
||||||
|
|
||||||
typedef typename Private::GenScatterImpl
|
typedef typename Private::GenScatterImpl
|
||||||
<
|
<
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::Typelist_ID ? TL::Private::Typelist_ID :
|
IS_TYPELIST(T)::type_id
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::AtomList_ID ? TL::Private::Typelist_ID :
|
>::template In<T, Unit>::LeftBase LeftBase;
|
||||||
IS_TYPELIST(T)::type_id == TL::Private::NullType_ID ? TL::Private::NullType_ID :
|
typedef typename Private::GenScatterImpl
|
||||||
TL::Private::NoneList_ID
|
<
|
||||||
|
IS_TYPELIST(T)::type_id
|
||||||
>::template In<T, Unit>::RightBase RightBase;
|
>::template In<T, Unit>::RightBase RightBase;
|
||||||
|
|
||||||
template <typename U> struct Rebind
|
template <typename U> struct Rebind
|
||||||
|
@ -269,11 +306,12 @@ namespace Private
|
||||||
// If Do is not a template and H& is used as parameter
|
// If Do is not a template and H& is used as parameter
|
||||||
// MSVC will give a linker error.
|
// MSVC will give a linker error.
|
||||||
template <class T>
|
template <class T>
|
||||||
static ResultType& Do(T& obj)
|
static ResultType& Do(H& obj, T*)
|
||||||
{
|
{
|
||||||
typedef typename T::RightBase RightBase;
|
//typedef typename T::RightBase RightBase;
|
||||||
|
//RightBase& rightBase = obj;
|
||||||
RightBase& rightBase = obj;
|
RightBase& rightBase = obj;
|
||||||
return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase);
|
return FieldHelper<i - 1>::template In<RightBase, Unit>::Do(rightBase, (int*)0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -317,7 +355,7 @@ namespace Private
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class T>
|
template <class T>
|
||||||
static ResultType& Do(T& obj)
|
static ResultType& Do(H& obj, T*)
|
||||||
{
|
{
|
||||||
LeftBase& leftBase = obj;
|
LeftBase& leftBase = obj;
|
||||||
return leftBase;
|
return leftBase;
|
||||||
|
@ -334,17 +372,14 @@ namespace Private
|
||||||
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
// returns a reference to Unit<T>, where Unit is the template used to generate H
|
||||||
// and T is the i-th type in the typelist
|
// and T is the i-th type in the typelist
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <unsigned int i, class TList, class UnitWrapper>
|
template <unsigned int i, class TList, class UnitWrapper>
|
||||||
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
|
typename FieldHelper<i>::template In<GenScatterHierarchy<TList, UnitWrapper>,UnitWrapper>::ResultType&
|
||||||
Field(GenScatterHierarchy<TList, UnitWrapper>& obj)
|
Field(GenScatterHierarchy<TList, UnitWrapper>& obj, Int2Type<i>)
|
||||||
{
|
{
|
||||||
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
|
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
|
||||||
|
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
|
||||||
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template GenLinearHierarchy
|
// class template GenLinearHierarchy
|
||||||
// Generates a linear hierarchy starting from a typelist and a template
|
// Generates a linear hierarchy starting from a typelist and a template
|
||||||
|
@ -386,7 +421,8 @@ namespace Private
|
||||||
typedef typename TList::Tail Tail;
|
typedef typename TList::Tail Tail;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result;
|
typedef typename
|
||||||
|
ApplyInnerType2<Unit, Head, GenLinearHierarchy<Tail, Unit, Root> >::type Result;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,7 +436,7 @@ namespace Private
|
||||||
typedef typename TList::Head Head;
|
typedef typename TList::Head Head;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef ApplyInnerType2<Unit,Head, Root>::type Result;
|
typedef typename ApplyInnerType2<Unit,Head, Root>::type Result;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -417,13 +453,12 @@ namespace Private
|
||||||
>
|
>
|
||||||
::template In<T, U, Root>::Result TempType;
|
::template In<T, U, Root>::Result TempType;
|
||||||
|
|
||||||
typedef typename
|
typedef Private::VC_Base_Workaround<TempType, Dummy> type;
|
||||||
Private::VC_Base_Workaround<TempType, Dummy> type;
|
|
||||||
|
|
||||||
// this is nothing more than a typedef to the created hierarchy (TempType).
|
// this is nothing more than a typedef to the created hierarchy (TempType).
|
||||||
// But if we try to inherit directly from TempType VC 6.0
|
// But if we try to inherit directly from TempType VC 6.0
|
||||||
// will produce a "Error C2516. : is not a legal base class."
|
// will produce a "Error C2516. : is not a legal base class."
|
||||||
typedef type::LeftBase Base;
|
typedef typename type::LeftBase Base;
|
||||||
};
|
};
|
||||||
} // namespace Private
|
} // namespace Private
|
||||||
|
|
||||||
|
@ -450,11 +485,26 @@ namespace Private
|
||||||
|
|
||||||
} // namespace Loki
|
} // namespace Loki
|
||||||
|
|
||||||
|
#if defined (_MSC_VER) && _MSC_VER <= 1300
|
||||||
|
#define FIELD(Obj, Nr) \
|
||||||
|
Field(Obj, Int2Type<Nr>())
|
||||||
|
#else
|
||||||
|
#define FIELD(Obj, Nr) \
|
||||||
|
Field<Nr>(Obj)
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Change log:
|
// Change log:
|
||||||
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
|
||||||
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
|
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
|
||||||
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6
|
// Oct 24, 2002: ported by Benjamin Kaufmann to MSVC 6
|
||||||
|
// Dec 08, 2002: Fixed problems with MSVC6-Version of GenScatterHierarchy when
|
||||||
|
// used with typelists containing equal types. B.K.
|
||||||
|
// New Version is ugly :-(
|
||||||
|
// Dec 08, 2002: Interface changed for Field-Function. The old version does not
|
||||||
|
// work correctly due to the "Explicitly Specified Template
|
||||||
|
// Functions Not Overloaded Correctly"-Bug
|
||||||
|
// (Microsoft KB Article - 240871). B.K.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
#undef IS_TYPELIST
|
#undef IS_TYPELIST
|
||||||
#endif // HIERARCHYGENERATORS_INC_
|
#endif // HIERARCHYGENERATORS_INC_
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// Last update: Dec 03, 2002
|
||||||
|
// Added qualification ::Loki::Private:: to types from the Private-Namespace
|
||||||
|
// Thanks to Adi Shavit
|
||||||
|
|
||||||
#ifndef MSVC6HELPERS__H
|
#ifndef MSVC6HELPERS__H
|
||||||
#define MSVC6HELPERS__H
|
#define MSVC6HELPERS__H
|
||||||
#if !defined (_MSC_VER) || _MSC_VER >= 1300
|
#if !defined (_MSC_VER) || _MSC_VER >= 1300
|
||||||
|
@ -7,6 +11,10 @@ namespace Loki
|
||||||
{
|
{
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
|
template <class T, class U>
|
||||||
|
struct VC_InaccessibleBase : public T
|
||||||
|
{};
|
||||||
|
|
||||||
// workaround for the "Error C2516. : is not a legal base class"
|
// workaround for the "Error C2516. : is not a legal base class"
|
||||||
// Use VC_Base_Workaround's LeftBase instead of the
|
// Use VC_Base_Workaround's LeftBase instead of the
|
||||||
// alleged illegal base class.
|
// alleged illegal base class.
|
||||||
|
@ -50,9 +58,9 @@ namespace Loki
|
||||||
{ template<class> struct In; };
|
{ template<class> struct In; };
|
||||||
|
|
||||||
template< typename T1 > struct Result : public
|
template< typename T1 > struct Result : public
|
||||||
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1>
|
VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1>
|
||||||
{
|
{
|
||||||
typedef VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base;
|
typedef VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1> Base;
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -72,7 +80,7 @@ namespace Loki
|
||||||
{template<class T, class U> struct In; };
|
{template<class T, class U> struct In; };
|
||||||
|
|
||||||
template< typename T1, typename T2 > struct Result : public
|
template< typename T1, typename T2 > struct Result : public
|
||||||
VC_WORKAROUND< AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2>
|
VC_WORKAROUND< ::Loki::Private::AlwaysFalse<TypeWithNestedTemplate>::value >::template In<T1, T2>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -88,9 +96,9 @@ namespace Loki
|
||||||
// i first saw this technique in boost's mpl library.
|
// i first saw this technique in boost's mpl library.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename F, typename T1>
|
template<typename F, typename T1>
|
||||||
struct Apply1 : Private::ApplyImpl1<F>::template Result<T1>
|
struct Apply1 : ::Loki::Private::ApplyImpl1<F>::template Result<T1>
|
||||||
{
|
{
|
||||||
typedef typename Private::ApplyImpl1<F>::template Result<T1>::Base Base;
|
typedef typename ::Loki::Private::ApplyImpl1<F>::template Result<T1>::Base Base;
|
||||||
};
|
};
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template Apply2
|
// class template Apply2
|
||||||
|
@ -100,7 +108,7 @@ namespace Loki
|
||||||
// i first saw this technique in boost's mpl library.
|
// i first saw this technique in boost's mpl library.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
template<typename F, typename T1, typename T2>
|
template<typename F, typename T1, typename T2>
|
||||||
struct Apply2 : Private::ApplyImpl2<F>::template Result<T1, T2>
|
struct Apply2 : ::Loki::Private::ApplyImpl2<F>::template Result<T1, T2>
|
||||||
{
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -121,7 +129,7 @@ namespace Loki
|
||||||
template<> struct Wrapper_VC<true>
|
template<> struct Wrapper_VC<true>
|
||||||
{ template<class X> struct In; };
|
{ template<class X> struct In; };
|
||||||
typedef typename
|
typedef typename
|
||||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
|
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
|
||||||
};
|
};
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// class template ApplyInnerType2
|
// class template ApplyInnerType2
|
||||||
|
@ -139,7 +147,7 @@ namespace Loki
|
||||||
template<> struct Wrapper_VC<true>
|
template<> struct Wrapper_VC<true>
|
||||||
{ template<class X, class Y> struct In; };
|
{ template<class X, class Y> struct In; };
|
||||||
typedef typename
|
typedef typename
|
||||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
|
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Wrapper, class T, class U, class V, class W>
|
template <class Wrapper, class T, class U, class V, class W>
|
||||||
|
@ -150,8 +158,9 @@ namespace Loki
|
||||||
template<> struct Wrapper_VC<true>
|
template<> struct Wrapper_VC<true>
|
||||||
{ template<class W, class X, class Y, class Z> struct In; };
|
{ template<class W, class X, class Y, class Z> struct In; };
|
||||||
typedef typename
|
typedef typename
|
||||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
|
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -1,5 +1,6 @@
|
||||||
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
|
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
|
Version: 0.3
|
||||||
|
|
||||||
Introduction/Compatibility:
|
Introduction/Compatibility:
|
||||||
---------------------------
|
---------------------------
|
||||||
|
@ -26,6 +27,32 @@ you must add SmallObj.cpp to your project/makefile.
|
||||||
|
|
||||||
If you use Singletons with longevity you must add Singleton.cpp to your project/makefile.
|
If you use Singletons with longevity you must add Singleton.cpp to your project/makefile.
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
|
||||||
|
Dec 08, 2002:
|
||||||
|
-------------
|
||||||
|
* In HierarchyGenerators.h: Sergey Khachatrian reported a bug
|
||||||
|
in GenScatterHierarchy when used with a typelist containing
|
||||||
|
equal types (e.g. GenScatterHierarchy<TYPELIST_2(int, int), UnitWrapper>
|
||||||
|
resp. Tuple<TYPELIST_2(int, int)>)
|
||||||
|
Fixing the bug I found another MSVC6-Problem in the Field-function.
|
||||||
|
The workaround for this problems results in an interface change.
|
||||||
|
|
||||||
|
please refer to the section "Interface changes" below for further information.
|
||||||
|
|
||||||
|
Dec 03, 2002
|
||||||
|
-------------
|
||||||
|
* In MSVC6Helpers.h: The original version failed to qualify some types from the
|
||||||
|
Private-Namespace.
|
||||||
|
Thanks to Adi Shavit for pointing that out
|
||||||
|
|
||||||
|
* In Threads.h: Changed wrong ctor/dtor names in ObjectLevelLockable.
|
||||||
|
Thanks to Adi Shavit for pointing that out
|
||||||
|
|
||||||
|
Nov 19, 2002:
|
||||||
|
-------------
|
||||||
|
* In SmartPtr.h: Changed template ctors. See Notes.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
------
|
------
|
||||||
|
@ -37,7 +64,6 @@ C. explicit template argument specification for member- and nonmeber functions.
|
||||||
D. covariant return types.
|
D. covariant return types.
|
||||||
E. Template parameters with a default type void
|
E. Template parameters with a default type void
|
||||||
F. return statements with an expression of type cv in functions with a return type of cv void.
|
F. return statements with an expression of type cv in functions with a return type of cv void.
|
||||||
G. Template-ctor resp. template assignment operator
|
|
||||||
|
|
||||||
Unfortunately the MSVC 6.0 supports neither of them.
|
Unfortunately the MSVC 6.0 supports neither of them.
|
||||||
|
|
||||||
|
@ -88,6 +114,29 @@ Unfortunately the MSVC 6.0 supports neither of them.
|
||||||
[/code]
|
[/code]
|
||||||
in this port.
|
in this port.
|
||||||
|
|
||||||
|
Update:
|
||||||
|
-------
|
||||||
|
The MSVC 6.0 sometimes does not overload normal functions depending
|
||||||
|
on explicit argument specification correctly (see: Microsoft KB Article - 240871)
|
||||||
|
The following code demonstrates the problem:
|
||||||
|
[code]
|
||||||
|
template <unsigned i, class T>
|
||||||
|
void BugDemonstration(T p)
|
||||||
|
{
|
||||||
|
printf("BugDemonstration called with i = %d\n", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
GenScatterHierarchy<TYPELIST_3(int, int, int), TestUnitWrapper> Bla;
|
||||||
|
// will always print: "BugDemonstration called with i = 2";
|
||||||
|
BugDemonstration<0>(Bla);
|
||||||
|
BugDemonstration<1>(Bla);
|
||||||
|
BugDemonstration<2>(Bla);
|
||||||
|
}
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
As a workaround i added dummy-parameters.
|
||||||
|
|
||||||
D. Virtual functions that use covariant return types (e.g. return a pointer to Derived)
|
D. Virtual functions that use covariant return types (e.g. return a pointer to Derived)
|
||||||
in the original library were changed so that they have exactly the
|
in the original library were changed so that they have exactly the
|
||||||
|
@ -96,41 +145,64 @@ Unfortunately the MSVC 6.0 supports neither of them.
|
||||||
E. All template parameters that have a default type of void in the original lib now
|
E. All template parameters that have a default type of void in the original lib now
|
||||||
have int as default type.
|
have int as default type.
|
||||||
|
|
||||||
F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent
|
F. In Functor.h I changed a ResultType of type void to VoidAsType (an udt). This change is transparent
|
||||||
for the user of Functor.
|
for the user of Functor.
|
||||||
Because I could not think of any general and transparent workaround I followed different
|
Because I could not think of any general and transparent workaround I followed different
|
||||||
strategies. In Visitor.h for example I created new classes (and macros) for the void-case.
|
strategies. In Visitor.h for example I created new classes (and macros) for the void-case.
|
||||||
In other places (for example: MultiMethod.h) this port simply fails to support void as
|
In other places (for example: MultiMethod.h) this port simply fails to support void as
|
||||||
return type :-(
|
return type :-(
|
||||||
|
|
||||||
G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version
|
Some words to template-ctors resp. template assignment operators:
|
||||||
is present. On the other hand the MSVC 6.0 allows explicit template specialization in class
|
The MSVC 6.0 introduces an order-dependency for template ctor
|
||||||
scope. I used this "feature" as a workaround for code like this:
|
resp. template assignemt operators.
|
||||||
[code]
|
If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
|
||||||
template <class T>
|
you *must* write the templated version first.
|
||||||
struct Foo
|
So instead of
|
||||||
{
|
[code]
|
||||||
Foo(const Foo&);
|
template <class T>
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
Foo(const Foo&)
|
||||||
|
{}
|
||||||
template <class U>
|
template <class U>
|
||||||
Foo(const Foo<U>&);
|
Foo(const Foo<U>& r)
|
||||||
};
|
{}
|
||||||
[/code]
|
};
|
||||||
|
[/code]
|
||||||
Under MSVC 6.0 the above code becomes:
|
you *need* to write:
|
||||||
[code]
|
[code]
|
||||||
template <class T>
|
template <class T>
|
||||||
struct Foo
|
struct Foo
|
||||||
{
|
{
|
||||||
template <class U>
|
template <class U>
|
||||||
Foo(const Foo<U>&);
|
Foo(const Foo<U>& r)
|
||||||
|
{}
|
||||||
|
|
||||||
// copy-ctor for Foos with equal T
|
Foo(const Foo& r)
|
||||||
// not valid c++
|
{}
|
||||||
template <>
|
};
|
||||||
Foo(const Foo&);
|
[/code]
|
||||||
};
|
|
||||||
[/code]
|
|
||||||
|
|
||||||
|
Many thanks to Nelson Elói for pointing that out and for providing me
|
||||||
|
with this solution.
|
||||||
|
|
||||||
|
The above solution unfortunately does not work if the template ctor does not have
|
||||||
|
the form of a copy-ctor. If you write something like this (as in the functor-class):
|
||||||
|
[code]
|
||||||
|
template <class T>
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
template <class Fun>
|
||||||
|
Foo(Fun r)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Foo(const Foo& r)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
[/code]
|
||||||
|
then the VC will no longer find a copy-ctor.
|
||||||
|
|
||||||
|
Because of this, i can't use Nelson Elói's solution in Functor.h
|
||||||
|
|
||||||
Interface changes:
|
Interface changes:
|
||||||
------------------
|
------------------
|
||||||
|
@ -180,6 +252,44 @@ Interface changes:
|
||||||
a nested-template class called 'In'. 'In' should only contain a typedef to the
|
a nested-template class called 'In'. 'In' should only contain a typedef to the
|
||||||
concrete Unit.
|
concrete Unit.
|
||||||
|
|
||||||
|
Update:
|
||||||
|
The port's original version of GenScatterHierarchy does not work when used
|
||||||
|
with typelists containing equal types.
|
||||||
|
The problem is due to a VC bug. The VC fails to compile code similar
|
||||||
|
to this, although it is perfectly legal.
|
||||||
|
[code]
|
||||||
|
template <class T>
|
||||||
|
class Wrapper
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct B : public Wrapper<T>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// ERROR: 'A<T>' : direct base 'Wrapper<T>' is inaccessible; already a base of 'B<T>'
|
||||||
|
template <class T>
|
||||||
|
class A : public B<T>, public Wrapper<T>
|
||||||
|
{};
|
||||||
|
[/code]
|
||||||
|
|
||||||
|
Unfortunately my workaround has a big drawback.
|
||||||
|
GenScatterHierarchy now has to generate a lot more classes.
|
||||||
|
Alexandrescu's original implementation generates 3*n classes (n - number of types in the typelist)
|
||||||
|
The old version of my port creates 4 * n + 1
|
||||||
|
The new version will create 5 * n
|
||||||
|
|
||||||
|
The fix also reveals the "Explicitly Specified Template Functions Not Overloaded Correctly"-Bug
|
||||||
|
(Microsoft KB Article - 240871) in the Field-Function taking a nontype int Parameter.
|
||||||
|
|
||||||
|
This leads to an interface change:
|
||||||
|
Instead of: Field<0>(obj)
|
||||||
|
one now has to write
|
||||||
|
Field(obj, Int2Type<0>());
|
||||||
|
|
||||||
|
I added a macro FIELD. Using this macro one can write
|
||||||
|
FIELD(obj, 0)
|
||||||
|
|
||||||
|
|
||||||
6. Factory.h
|
6. Factory.h
|
||||||
|
|
||||||
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter.
|
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter.
|
||||||
|
|
|
@ -13,21 +13,18 @@
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: Oct 26, 2002
|
// Last update: Nov 19, 2002
|
||||||
|
|
||||||
// replaced all template template parameters with 'normal' parameters
|
// replaced all template template parameters with 'normal' parameters
|
||||||
// For each Policy there is now a wrapper-class (non template class)
|
// For each Policy there is now a wrapper-class (non template class)
|
||||||
// containing a nested template class called In which
|
// containing a nested template class called In which
|
||||||
// provides a typedef (type) to the real Policy-class
|
// provides a typedef (type) to the real Policy-class
|
||||||
//
|
//
|
||||||
// VC special: The MSVC 6.0 has problems with template ctors resp. template
|
// VC special: The MSVC 6.0 introduces an order-dependency for template ctor
|
||||||
// assignemt operators. If there exists a template copy ctor (a template op=) the
|
// resp. template assignemt operators.
|
||||||
// compiler will complain about a non-template version. On the other hand,
|
// If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
|
||||||
// if one does not provide a non-template version and one tries to
|
// you *must* write the templated version first.
|
||||||
// initialize a new object with one having the same type the compiler will synthesize
|
// So instead of
|
||||||
// a default version (the same for assignment).
|
|
||||||
// Because the MSVC allows explicit specialization in class scope i used
|
|
||||||
// this as a workaround.
|
|
||||||
// Instead of:
|
|
||||||
// template <class T>
|
// template <class T>
|
||||||
// struct Foo
|
// struct Foo
|
||||||
// {
|
// {
|
||||||
|
@ -37,19 +34,21 @@
|
||||||
// Foo(const Foo<U>& r)
|
// Foo(const Foo<U>& r)
|
||||||
// {}
|
// {}
|
||||||
// };
|
// };
|
||||||
//
|
// you *need* to write:
|
||||||
// this port uses:
|
|
||||||
//
|
|
||||||
// template <class T>
|
// template <class T>
|
||||||
// struct Foo
|
// struct Foo
|
||||||
// {
|
// {
|
||||||
// template <class U>
|
// template <class U>
|
||||||
// Foo(const Foo<U>& r)
|
// Foo(const Foo<U>& r)
|
||||||
// {}
|
// {}
|
||||||
// template <>
|
//
|
||||||
// Foo(const Foo& r)
|
// Foo(const Foo& r)
|
||||||
// {}
|
// {}
|
||||||
// };
|
// };
|
||||||
|
//
|
||||||
|
// Many thanks to Nelson Elói for pointing that out and for providing me
|
||||||
|
// with this solution
|
||||||
|
|
||||||
|
|
||||||
#ifndef SMARTPTR_INC_
|
#ifndef SMARTPTR_INC_
|
||||||
#define SMARTPTR_INC_
|
#define SMARTPTR_INC_
|
||||||
|
@ -93,18 +92,15 @@ namespace Loki
|
||||||
|
|
||||||
// The storage policy doesn't initialize the stored pointer
|
// The storage policy doesn't initialize the stored pointer
|
||||||
// which will be initialized by the OwnershipPolicy's Clone fn
|
// which will be initialized by the OwnershipPolicy's Clone fn
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
DefaultSPStorage(const DefaultSPStorage&)
|
// do not alter the order of the following two constructors
|
||||||
{}
|
// otherwise the MSVC 6.0 will not compile the class.
|
||||||
#endif
|
|
||||||
template <class U>
|
template <class U>
|
||||||
DefaultSPStorage(const DefaultSPStorage<U>&)
|
DefaultSPStorage(const DefaultSPStorage<U>&) {}
|
||||||
{}
|
|
||||||
#if _MSC_VER <= 1200
|
|
||||||
template <>
|
|
||||||
DefaultSPStorage(const DefaultSPStorage&)
|
DefaultSPStorage(const DefaultSPStorage&)
|
||||||
{}
|
{}
|
||||||
#endif
|
|
||||||
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
|
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
|
||||||
|
|
||||||
PointerType operator->() const { return pointee_; }
|
PointerType operator->() const { return pointee_; }
|
||||||
|
@ -166,11 +162,8 @@ namespace Loki
|
||||||
*pCount_ = 1;
|
*pCount_ = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
// do not alter the order of the following two constructors
|
||||||
RefCounted(const RefCounted& rhs)
|
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||||
: pCount_(rhs.pCount_)
|
|
||||||
{}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// MWCW lacks template friends, hence the following kludge
|
// MWCW lacks template friends, hence the following kludge
|
||||||
template <typename P1>
|
template <typename P1>
|
||||||
|
@ -178,12 +171,10 @@ namespace Loki
|
||||||
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
|
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
#if _MSC_VER <= 1200
|
|
||||||
template<>
|
|
||||||
RefCounted(const RefCounted& rhs)
|
RefCounted(const RefCounted& rhs)
|
||||||
: pCount_(rhs.pCount_)
|
: pCount_(rhs.pCount_)
|
||||||
{}
|
{}
|
||||||
#endif
|
|
||||||
P Clone(const P& val)
|
P Clone(const P& val)
|
||||||
{
|
{
|
||||||
++*pCount_;
|
++*pCount_;
|
||||||
|
@ -977,10 +968,8 @@ namespace Private
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER)
|
// do not alter the order of the following three constructors
|
||||||
SmartPtr(CopyArg& rhs)
|
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
|
||||||
#endif
|
|
||||||
template
|
template
|
||||||
<
|
<
|
||||||
typename T1,
|
typename T1,
|
||||||
|
@ -1005,28 +994,15 @@ namespace Private
|
||||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||||
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
||||||
|
|
||||||
#if _MSC_VER <= 1200
|
|
||||||
|
|
||||||
template <>
|
|
||||||
SmartPtr(CopyArg& rhs)
|
SmartPtr(CopyArg& rhs)
|
||||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||||
#endif
|
|
||||||
|
|
||||||
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
||||||
SmartPtr(ByRef<SmartPtr> rhs)
|
|
||||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
operator ByRef<SmartPtr>()
|
operator ByRef<SmartPtr>()
|
||||||
{ return ByRef<SmartPtr>(*this); }
|
{ return ByRef<SmartPtr>(*this); }
|
||||||
#if !defined(_MSC_VER)
|
|
||||||
SmartPtr& operator=(CopyArg& rhs)
|
|
||||||
{
|
// do not alter the order of the following three copy-assignment operators
|
||||||
SmartPtr temp(rhs);
|
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||||
temp.Swap(*this);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
template
|
template
|
||||||
<
|
<
|
||||||
typename T1,
|
typename T1,
|
||||||
|
@ -1057,15 +1033,13 @@ namespace Private
|
||||||
temp.Swap(*this);
|
temp.Swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#if _MSC_VER <= 1200
|
|
||||||
template<>
|
|
||||||
SmartPtr& operator=(CopyArg& rhs)
|
SmartPtr& operator=(CopyArg& rhs)
|
||||||
{
|
{
|
||||||
SmartPtr temp(rhs);
|
SmartPtr temp(rhs);
|
||||||
temp.Swap(*this);
|
temp.Swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
void Swap(SmartPtr& rhs)
|
void Swap(SmartPtr& rhs)
|
||||||
{
|
{
|
||||||
OP::Swap(rhs);
|
OP::Swap(rhs);
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
// affects only default template arguments
|
// affects only default template arguments
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Last update: Oct 07, 2002
|
// Last update: Dec 03, 2002
|
||||||
// note: In this VC 6 port all template policies become non-templates with
|
// note: In this VC 6 port all template policies become non-templates with
|
||||||
// either member-template functions or a nested template struct named In
|
// either member-template functions or a nested template struct named In
|
||||||
|
|
||||||
|
// Changed wrong ctor/dtor names in ObjectLevelLockable.
|
||||||
|
// Thanks to Adi Shavit for pointing that out
|
||||||
|
|
||||||
#ifndef DEFAULT_THREADING
|
#ifndef DEFAULT_THREADING
|
||||||
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,12 +93,12 @@ namespace Loki
|
||||||
CRITICAL_SECTION mtx_;
|
CRITICAL_SECTION mtx_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectLevelLockable()
|
In()
|
||||||
{
|
{
|
||||||
::InitializeCriticalSection(&mtx_);
|
::InitializeCriticalSection(&mtx_);
|
||||||
}
|
}
|
||||||
|
|
||||||
~ObjectLevelLockable()
|
~In()
|
||||||
{
|
{
|
||||||
::DeleteCriticalSection(&mtx_);
|
::DeleteCriticalSection(&mtx_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace Loki
|
||||||
template <int v>
|
template <int v>
|
||||||
struct Int2Type
|
struct Int2Type
|
||||||
{
|
{
|
||||||
|
Int2Type() {}
|
||||||
enum { value = v };
|
enum { value = v };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ namespace Loki
|
||||||
class TypeTraits
|
class TypeTraits
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// static T MakeT(...);
|
static T MakeT(...);
|
||||||
template <class U> struct Wrap{};
|
template <class U> struct Wrap{};
|
||||||
struct pointer_helper
|
struct pointer_helper
|
||||||
{
|
{
|
||||||
|
@ -232,8 +232,8 @@ namespace Loki
|
||||||
enum {isReference = sizeof(
|
enum {isReference = sizeof(
|
||||||
is_reference_helper2(
|
is_reference_helper2(
|
||||||
is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)};
|
is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)};
|
||||||
// enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
|
enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
|
||||||
// enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
|
enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
|
||||||
enum {isArray = sizeof(
|
enum {isArray = sizeof(
|
||||||
is_array_helper1(
|
is_array_helper1(
|
||||||
is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)};
|
is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)};
|
||||||
|
@ -264,7 +264,7 @@ namespace Loki
|
||||||
isVolatile =
|
isVolatile =
|
||||||
sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES)
|
sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES)
|
||||||
};
|
};
|
||||||
enum { isScalar = isStdArith /* || isPointer */ /* || isMemberPointer */ };
|
enum { isScalar = isStdArith || isPointer || isMemberPointer};
|
||||||
private:
|
private:
|
||||||
typedef typename Private::AdjReference<isReference || isVoid>::
|
typedef typename Private::AdjReference<isReference || isVoid>::
|
||||||
template In<T>::Result AdjType;
|
template In<T>::Result AdjType;
|
||||||
|
|
Loading…
Reference in a new issue