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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Oct 24, 2002
|
||||
// Last update: Dec 08, 2002
|
||||
|
||||
|
||||
#ifndef HIERARCHYGENERATORS_INC_
|
||||
#define HIERARCHYGENERATORS_INC_
|
||||
|
@ -68,15 +69,40 @@ namespace Loki
|
|||
//
|
||||
// See "Metaprogramming VC++ - more of Loki ported" from Mat Marcus
|
||||
// (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;
|
||||
|
||||
namespace Private
|
||||
{
|
||||
|
||||
template <class T, class U>
|
||||
class InheritFromTwo : public T, public U
|
||||
{
|
||||
public:
|
||||
struct InheritFromTwo : public T, public U
|
||||
{
|
||||
};
|
||||
|
||||
template <int tag>
|
||||
|
@ -90,16 +116,34 @@ namespace Private
|
|||
struct In : public GenScatterHierarchy<typename T::Head,MetaFunctionWrapper>
|
||||
{
|
||||
typedef
|
||||
InheritFromTwo < GenScatterHierarchy<typename T::Head,
|
||||
MetaFunctionWrapper>,
|
||||
InheritFromTwo < VC_InaccessibleBase<GenScatterHierarchy<typename T::Head,
|
||||
MetaFunctionWrapper>, typename T::Tail>,
|
||||
GenScatterHierarchy<typename T::Tail,
|
||||
MetaFunctionWrapper>
|
||||
> 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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
template <>
|
||||
struct GenScatterImpl<TL::Private::NoneList_ID>
|
||||
|
@ -111,7 +155,9 @@ namespace Private
|
|||
ApplyInnerType<MetaFunctionWrapper, AtomicType>::type type;
|
||||
typedef type LeftBase;
|
||||
typedef EmptyType RightBase;
|
||||
//typedef AtomicType::THIS_SELECTED bla;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// Specialization for NullType
|
||||
|
@ -127,14 +173,11 @@ namespace Private
|
|||
};
|
||||
};
|
||||
} // end namespace Private
|
||||
|
||||
|
||||
template <class T, class Unit>
|
||||
class GenScatterHierarchy : public 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
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::type
|
||||
{
|
||||
public:
|
||||
|
@ -142,28 +185,22 @@ namespace Private
|
|||
<
|
||||
TL::Private::IsTypelist<T>::value, T, void
|
||||
>::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
|
||||
<
|
||||
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>::RightBase RightBase;
|
||||
|
||||
|
||||
typedef typename Private::GenScatterImpl
|
||||
<
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::LeftBase LeftBase;
|
||||
typedef typename Private::GenScatterImpl
|
||||
<
|
||||
IS_TYPELIST(T)::type_id
|
||||
>::template In<T, Unit>::RightBase RightBase;
|
||||
|
||||
template <typename U> struct Rebind
|
||||
{
|
||||
typedef ApplyInnerType<Unit, U>::type Result;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// function template Field
|
||||
// Accesses a field in an object of a type generated with GenScatterHierarchy
|
||||
|
@ -269,11 +306,12 @@ namespace Private
|
|||
// If Do is not a template and H& is used as parameter
|
||||
// MSVC will give a linker error.
|
||||
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;
|
||||
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:
|
||||
template <class T>
|
||||
static ResultType& Do(T& obj)
|
||||
static ResultType& Do(H& obj, T*)
|
||||
{
|
||||
LeftBase& leftBase = obj;
|
||||
return leftBase;
|
||||
|
@ -334,17 +372,14 @@ namespace Private
|
|||
// 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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <unsigned int i, class TList, class UnitWrapper>
|
||||
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;
|
||||
|
||||
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj);
|
||||
typedef typename GenScatterHierarchy<TList, UnitWrapper> H;
|
||||
return FieldHelper<i>::template In<H, UnitWrapper>::Do(obj, (int*)0);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template GenLinearHierarchy
|
||||
// Generates a linear hierarchy starting from a typelist and a template
|
||||
|
@ -386,7 +421,8 @@ namespace Private
|
|||
typedef typename TList::Tail Tail;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
typedef typename
|
||||
Private::VC_Base_Workaround<TempType, Dummy> type;
|
||||
typedef Private::VC_Base_Workaround<TempType, Dummy> type;
|
||||
|
||||
// this is nothing more than a typedef to the created hierarchy (TempType).
|
||||
// But if we try to inherit directly from TempType VC 6.0
|
||||
// will produce a "Error C2516. : is not a legal base class."
|
||||
typedef type::LeftBase Base;
|
||||
typedef typename type::LeftBase Base;
|
||||
};
|
||||
} // namespace Private
|
||||
|
||||
|
@ -450,11 +485,26 @@ namespace Private
|
|||
|
||||
} // 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:
|
||||
// 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.
|
||||
// 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
|
||||
#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
|
||||
#define MSVC6HELPERS__H
|
||||
#if !defined (_MSC_VER) || _MSC_VER >= 1300
|
||||
|
@ -7,18 +11,22 @@ namespace Loki
|
|||
{
|
||||
namespace Private
|
||||
{
|
||||
template <class T, class U>
|
||||
struct VC_InaccessibleBase : public T
|
||||
{};
|
||||
|
||||
// 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.
|
||||
template <class T, class U>
|
||||
struct VC_Base_Workaround : public T, public U
|
||||
{
|
||||
typedef T LeftBase;
|
||||
};
|
||||
|
||||
|
||||
// MSVC 6.0 does not allow the return of
|
||||
// expressions of type "cv void" in a functions with a return
|
||||
// type of cv void (6.6.3).
|
||||
// expressions of type "cv void" in a functions with a return
|
||||
// type of cv void (6.6.3).
|
||||
// Functor.h uses this Type as a workaround.
|
||||
struct VoidAsType {};
|
||||
|
||||
|
@ -50,10 +58,10 @@ namespace Loki
|
|||
{ template<class> struct In; };
|
||||
|
||||
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< 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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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
|
||||
|
@ -100,9 +108,9 @@ namespace Loki
|
|||
// i first saw this technique in boost's mpl library.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
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>
|
||||
{
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -117,11 +125,11 @@ namespace Loki
|
|||
struct ApplyInnerType
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class X> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T>::type type;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// class template ApplyInnerType2
|
||||
|
@ -135,23 +143,24 @@ namespace Loki
|
|||
struct ApplyInnerType2
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class X, class Y> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
|
||||
};
|
||||
|
||||
template <class Wrapper, class T, class U, class V, class W>
|
||||
struct ApplyInnerType4
|
||||
{
|
||||
template<bool> struct Wrapper_VC : Wrapper {};
|
||||
|
||||
|
||||
template<> struct Wrapper_VC<true>
|
||||
{ template<class W, class X, class Y, class Z> struct In; };
|
||||
typedef typename
|
||||
Wrapper_VC<Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
|
||||
typedef typename
|
||||
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
|
@ -1,11 +1,12 @@
|
|||
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
|
||||
-------------------------------------------------------------------
|
||||
Version: 0.3
|
||||
|
||||
Introduction/Compatibility:
|
||||
---------------------------
|
||||
This is a partial MSVC 6.0 Sp5 compatible port of Andrei Alexandrescu's excellent Loki Library.
|
||||
Because I could not retain the originial interface in all places, this port is not
|
||||
compatible to the original library and therefore code using this port *cannot* generally be
|
||||
Because I could not retain the originial interface in all places, this port is not
|
||||
compatible to the original library and therefore code using this port *cannot* generally be
|
||||
used together with the original lib.
|
||||
This is, of course, a great pity.
|
||||
So if you know of a complete and full interface-compatible VC 6.0
|
||||
|
@ -13,19 +14,45 @@ port or if you know how to improve this port, please let me know.
|
|||
|
||||
Contact:
|
||||
--------
|
||||
For any suggestions, bug reports, comments and questions please email me to
|
||||
For any suggestions, bug reports, comments and questions please email me to
|
||||
Hume@c-plusplus.de
|
||||
|
||||
Using this port:
|
||||
----------------
|
||||
To use this port, simply extract the files from the archive, give your compiler access to
|
||||
To use this port, simply extract the files from the archive, give your compiler access to
|
||||
their path, and include them appropriately in your code via #include.
|
||||
|
||||
If you use the small object allocator directly or indirectly (through the Functor class)
|
||||
If you use the small object allocator directly or indirectly (through the Functor class)
|
||||
you must add SmallObj.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:
|
||||
------
|
||||
|
@ -37,18 +64,17 @@ C. explicit template argument specification for member- and nonmeber functions.
|
|||
D. covariant return types.
|
||||
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.
|
||||
G. Template-ctor resp. template assignment operator
|
||||
|
||||
Unfortunately the MSVC 6.0 supports neither of them.
|
||||
|
||||
A. I used various techniques to simulate partial template specialization. In some cases
|
||||
these techniques allowed me to retain the original interfaces but often that was not
|
||||
possible (or better: i did not find a proper solution). In any case it leads
|
||||
possible (or better: i did not find a proper solution). In any case it leads
|
||||
to increasing code complexity :-)
|
||||
|
||||
B. One way to simulate template template parameters is to replace the template class with
|
||||
a normal class containing a nested template class. You then move the original functionality
|
||||
to the nested class.
|
||||
to the nested class.
|
||||
The problem with this approach is MSVC's 'dependent template typedef bug'. MSVC 6.0 does not
|
||||
allow something like this:
|
||||
|
||||
|
@ -58,17 +84,17 @@ Unfortunately the MSVC 6.0 supports neither of them.
|
|||
{
|
||||
// 'error C1001 - Internal Compiler Error' here
|
||||
typedef typename APolicy::template In<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
[/code]
|
||||
|
||||
To make a long story short, I finally decided to use boost::mpl's apply-technique to
|
||||
To make a long story short, I finally decided to use boost::mpl's apply-technique to
|
||||
simulate template template parameters. This approach works fine with MSVC 6.0. But be warned,
|
||||
this technique uses not valid C++.
|
||||
Of course, replacing template template parameters always results in some interface changes.
|
||||
Of course, replacing template template parameters always results in some interface changes.
|
||||
|
||||
C. I added dummy-Parameters to (Member-)Functions that depend on explicit template
|
||||
argument specification. These dummy-Parameters help the compiler in deducing the template
|
||||
C. I added dummy-Parameters to (Member-)Functions that depend on explicit template
|
||||
argument specification. These dummy-Parameters help the compiler in deducing the template
|
||||
parameters that otherwise need to be explicitly specified.
|
||||
Example:
|
||||
[code]
|
||||
|
@ -88,103 +114,187 @@ Unfortunately the MSVC 6.0 supports neither of them.
|
|||
[/code]
|
||||
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)
|
||||
in the original library were changed so that they have exactly the
|
||||
same return type as the original virtual function (e.g. return a pointer to Base).
|
||||
|
||||
|
||||
E. All template parameters that have a default type of void in the original lib now
|
||||
have int as default type.
|
||||
|
||||
F. In Functor.h I changed a ResultType of type void to VoidAsType (a udt). This change is transparent
|
||||
for the user of Functor.
|
||||
F. In Functor.h I changed a ResultType of type void to VoidAsType (an udt). This change is transparent
|
||||
for the user of Functor.
|
||||
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.
|
||||
In other places (for example: MultiMethod.h) this port simply fails to support void as
|
||||
return type :-(
|
||||
|
||||
G. The MSVC 6.0 does not recognize a copy-ctor resp. a copy-assignment if a templated version
|
||||
is present. On the other hand the MSVC 6.0 allows explicit template specialization in class
|
||||
scope. I used this "feature" as a workaround for code like this:
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
Foo(const Foo&);
|
||||
template <class U>
|
||||
Foo(const Foo<U>&);
|
||||
};
|
||||
[/code]
|
||||
|
||||
Under MSVC 6.0 the above code becomes:
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
template <class U>
|
||||
Foo(const Foo<U>&);
|
||||
Some words to template-ctors resp. template assignment operators:
|
||||
The MSVC 6.0 introduces an order-dependency for template ctor
|
||||
resp. template assignemt operators.
|
||||
If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
|
||||
you *must* write the templated version first.
|
||||
So instead of
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
Foo(const Foo&)
|
||||
{}
|
||||
template <class U>
|
||||
Foo(const Foo<U>& r)
|
||||
{}
|
||||
};
|
||||
[/code]
|
||||
you *need* to write:
|
||||
[code]
|
||||
template <class T>
|
||||
struct Foo
|
||||
{
|
||||
template <class U>
|
||||
Foo(const Foo<U>& r)
|
||||
{}
|
||||
|
||||
// copy-ctor for Foos with equal T
|
||||
// not valid c++
|
||||
template <>
|
||||
Foo(const Foo&);
|
||||
};
|
||||
[/code]
|
||||
Foo(const Foo& r)
|
||||
{}
|
||||
};
|
||||
[/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:
|
||||
------------------
|
||||
1. In Threads.h:
|
||||
|
||||
* Thread-Policies changed from class templates to normal classes containing a
|
||||
nested class template 'In'.
|
||||
|
||||
* Thread-Policies changed from class templates to normal classes containing a
|
||||
nested class template 'In'.
|
||||
|
||||
consequences:
|
||||
This change is not very dramatic because it won't break code using this port when
|
||||
switching to the original library (only new Thread-Policies must be changed)
|
||||
|
||||
2. In Singleton.h:
|
||||
|
||||
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
|
||||
Member-Templates.
|
||||
|
||||
* The Creation- and Lifetime-Policies are no longer class templates. Instead they all use
|
||||
Member-Templates.
|
||||
|
||||
consequences:
|
||||
Again this change will only break new Policies when switching to the
|
||||
original library.
|
||||
|
||||
3. In Functor.h:
|
||||
|
||||
|
||||
* No covariant return types.
|
||||
|
||||
|
||||
consequences:
|
||||
DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return
|
||||
DoClone always returns a FunctorImplBase<R, ThreadingModel>* where R is the functor's return
|
||||
type and ThreadingModel its current ThreadingModel.
|
||||
|
||||
4. TypeTraits.h
|
||||
|
||||
4. TypeTraits.h
|
||||
|
||||
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class provides not
|
||||
all the stuff provided by the original library's version.
|
||||
|
||||
|
||||
|
||||
5. HierarchyGenerator.h
|
||||
|
||||
|
||||
* I used Mat Marcus' approach to port GenScatterHierarchy.
|
||||
See http://lists.boost.org/MailArchives/boost/msg20915.php) for the consequences.
|
||||
|
||||
* Same for GenLinearHierarchy
|
||||
|
||||
* Unit is no longer a template template parameter.
|
||||
|
||||
|
||||
consequences:
|
||||
For every concrete unit-template there must be a normal class containing
|
||||
a nested-template class called 'In'. 'In' should only contain a typedef to the
|
||||
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
|
||||
|
||||
|
||||
* The Error-Policy for Factory and CloneFactory is no longer a template template parameter.
|
||||
Use a class with member-templates instead.
|
||||
|
||||
Use a class with member-templates instead.
|
||||
|
||||
consequences:
|
||||
This change will only break new Policies when switching to the
|
||||
original library.
|
||||
|
@ -192,7 +302,7 @@ Interface changes:
|
|||
7. AbstractFactory.h
|
||||
|
||||
* no covariant return types
|
||||
|
||||
|
||||
* no template template parameters
|
||||
For every concrete Factory-Unit there must be a normal class containing
|
||||
a nested-template class called 'In'. 'In' shall contain a typedef to the
|
||||
|
@ -203,7 +313,7 @@ Interface changes:
|
|||
ConcProduct* p = aFactory.Create<ConcProduct>();
|
||||
to
|
||||
ConcProduct* p = aFactory.Create((ConcProduct*)0);
|
||||
|
||||
|
||||
|
||||
8. SmartPtr.h
|
||||
|
||||
|
@ -214,7 +324,7 @@ Interface changes:
|
|||
|
||||
9. Visitor.h
|
||||
|
||||
* no template template parameters
|
||||
* no template template parameters
|
||||
(see 7.for a description of the consequences)
|
||||
|
||||
* This port fails to correctly support void return types. As a workaround it provides
|
||||
|
@ -229,7 +339,7 @@ Interface changes:
|
|||
|
||||
* This port does not support functions with return type void.
|
||||
|
||||
* dummy parameters were added to functions that otherwise would depend on
|
||||
* dummy parameters were added to functions that otherwise would depend on
|
||||
explicit template argument specification (14.8.1).
|
||||
|
||||
|
||||
|
|
|
@ -13,21 +13,18 @@
|
|||
// without express or implied warranty.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Last update: Oct 26, 2002
|
||||
// Last update: Nov 19, 2002
|
||||
|
||||
// replaced all template template parameters with 'normal' parameters
|
||||
// For each Policy there is now a wrapper-class (non template class)
|
||||
// containing a nested template class called In which
|
||||
// provides a typedef (type) to the real Policy-class
|
||||
//
|
||||
// VC special: The MSVC 6.0 has problems with template ctors resp. template
|
||||
// assignemt operators. If there exists a template copy ctor (a template op=) the
|
||||
// compiler will complain about a non-template version. On the other hand,
|
||||
// if one does not provide a non-template version and one tries to
|
||||
// initialize a new object with one having the same type the compiler will synthesize
|
||||
// a default version (the same for assignment).
|
||||
// Because the MSVC allows explicit specialization in class scope i used
|
||||
// this as a workaround.
|
||||
// Instead of:
|
||||
// VC special: The MSVC 6.0 introduces an order-dependency for template ctor
|
||||
// resp. template assignemt operators.
|
||||
// If you need both a copy-ctor and a template copy ctor (same for copy-assignment), then
|
||||
// you *must* write the templated version first.
|
||||
// So instead of
|
||||
// template <class T>
|
||||
// struct Foo
|
||||
// {
|
||||
|
@ -37,19 +34,21 @@
|
|||
// Foo(const Foo<U>& r)
|
||||
// {}
|
||||
// };
|
||||
//
|
||||
// this port uses:
|
||||
//
|
||||
// you *need* to write:
|
||||
// template <class T>
|
||||
// struct Foo
|
||||
// {
|
||||
// template <class U>
|
||||
// Foo(const Foo<U>& r)
|
||||
// {}
|
||||
// template <>
|
||||
//
|
||||
// Foo(const Foo& r)
|
||||
// {}
|
||||
// };
|
||||
//
|
||||
// Many thanks to Nelson Elói for pointing that out and for providing me
|
||||
// with this solution
|
||||
|
||||
|
||||
#ifndef SMARTPTR_INC_
|
||||
#define SMARTPTR_INC_
|
||||
|
@ -93,19 +92,16 @@ namespace Loki
|
|||
|
||||
// The storage policy doesn't initialize the stored pointer
|
||||
// which will be initialized by the OwnershipPolicy's Clone fn
|
||||
#if !defined(_MSC_VER)
|
||||
|
||||
// do not alter the order of the following two constructors
|
||||
// otherwise the MSVC 6.0 will not compile the class.
|
||||
template <class U>
|
||||
DefaultSPStorage(const DefaultSPStorage<U>&) {}
|
||||
|
||||
DefaultSPStorage(const DefaultSPStorage&)
|
||||
{}
|
||||
#endif
|
||||
template <class U>
|
||||
DefaultSPStorage(const DefaultSPStorage<U>&)
|
||||
{}
|
||||
#if _MSC_VER <= 1200
|
||||
template <>
|
||||
DefaultSPStorage(const DefaultSPStorage&)
|
||||
{}
|
||||
#endif
|
||||
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
|
||||
|
||||
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
|
||||
|
||||
PointerType operator->() const { return pointee_; }
|
||||
|
||||
|
@ -166,24 +162,19 @@ namespace Loki
|
|||
*pCount_ = 1;
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
RefCounted(const RefCounted& rhs)
|
||||
: pCount_(rhs.pCount_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
// MWCW lacks template friends, hence the following kludge
|
||||
// do not alter the order of the following two constructors
|
||||
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||
|
||||
// MWCW lacks template friends, hence the following kludge
|
||||
template <typename P1>
|
||||
RefCounted(const RefCounted<P1>& rhs)
|
||||
: pCount_(reinterpret_cast<const RefCounted&>(rhs).pCount_)
|
||||
{}
|
||||
|
||||
#if _MSC_VER <= 1200
|
||||
template<>
|
||||
|
||||
RefCounted(const RefCounted& rhs)
|
||||
: pCount_(rhs.pCount_)
|
||||
{}
|
||||
#endif
|
||||
|
||||
P Clone(const P& val)
|
||||
{
|
||||
++*pCount_;
|
||||
|
@ -976,11 +967,9 @@ namespace Private
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
SmartPtr(CopyArg& rhs)
|
||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||
#endif
|
||||
|
||||
// do not alter the order of the following three constructors
|
||||
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||
template
|
||||
<
|
||||
typename T1,
|
||||
|
@ -1005,29 +994,16 @@ namespace Private
|
|||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
||||
|
||||
#if _MSC_VER <= 1200
|
||||
|
||||
template <>
|
||||
SmartPtr(CopyArg& rhs)
|
||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||
#endif
|
||||
|
||||
{ GetImplRef(*this) = OP::Clone(GetImplRef(rhs)); }
|
||||
SmartPtr(ByRef<SmartPtr> rhs)
|
||||
: SP(rhs), OP(rhs), KP(rhs), CP(rhs)
|
||||
{}
|
||||
|
||||
operator ByRef<SmartPtr>()
|
||||
{ return ByRef<SmartPtr>(*this); }
|
||||
#if !defined(_MSC_VER)
|
||||
SmartPtr& operator=(CopyArg& rhs)
|
||||
{
|
||||
SmartPtr temp(rhs);
|
||||
temp.Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
template
|
||||
|
||||
|
||||
// do not alter the order of the following three copy-assignment operators
|
||||
// otherwise the MSVC 6.0 will fail to compile the class.
|
||||
template
|
||||
<
|
||||
typename T1,
|
||||
class OP1,
|
||||
|
@ -1057,15 +1033,13 @@ namespace Private
|
|||
temp.Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#if _MSC_VER <= 1200
|
||||
template<>
|
||||
|
||||
SmartPtr& operator=(CopyArg& rhs)
|
||||
{
|
||||
SmartPtr temp(rhs);
|
||||
temp.Swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
void Swap(SmartPtr& rhs)
|
||||
{
|
||||
OP::Swap(rhs);
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
// 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
|
||||
// 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
|
||||
#define DEFAULT_THREADING /**/ ::Loki::SingleThreaded
|
||||
#endif
|
||||
|
@ -90,12 +93,12 @@ namespace Loki
|
|||
CRITICAL_SECTION mtx_;
|
||||
|
||||
public:
|
||||
ObjectLevelLockable()
|
||||
In()
|
||||
{
|
||||
::InitializeCriticalSection(&mtx_);
|
||||
}
|
||||
|
||||
~ObjectLevelLockable()
|
||||
~In()
|
||||
{
|
||||
::DeleteCriticalSection(&mtx_);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ namespace Loki
|
|||
template <int v>
|
||||
struct Int2Type
|
||||
{
|
||||
enum { value = v };
|
||||
Int2Type() {}
|
||||
enum { value = v };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace Loki
|
|||
class TypeTraits
|
||||
{
|
||||
private:
|
||||
// static T MakeT(...);
|
||||
static T MakeT(...);
|
||||
template <class U> struct Wrap{};
|
||||
struct pointer_helper
|
||||
{
|
||||
|
@ -232,8 +232,8 @@ namespace Loki
|
|||
enum {isReference = sizeof(
|
||||
is_reference_helper2(
|
||||
is_reference_helper1(Wrap<T>()))) == sizeof(Private::YES)};
|
||||
// enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
|
||||
// enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
|
||||
enum {isPointer = sizeof(is_pointer(MakeT())) == sizeof(Private::YES)};
|
||||
enum {isMemberPointer = sizeof(is_pointer2member(MakeT())) == sizeof(Private::YES)};
|
||||
enum {isArray = sizeof(
|
||||
is_array_helper1(
|
||||
is_array_helper2(Wrap<T>()))) == sizeof(Private::YES)};
|
||||
|
@ -264,7 +264,7 @@ namespace Loki
|
|||
isVolatile =
|
||||
sizeof(is_volatile(Wrap<T>())) == sizeof(Private::YES)
|
||||
};
|
||||
enum { isScalar = isStdArith /* || isPointer */ /* || isMemberPointer */ };
|
||||
enum { isScalar = isStdArith || isPointer || isMemberPointer};
|
||||
private:
|
||||
typedef typename Private::AdjReference<isReference || isVoid>::
|
||||
template In<T>::Result AdjType;
|
||||
|
|
Loading…
Reference in a new issue