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:
tslettebo 2003-01-10 01:33:21 +00:00
parent ca94249f94
commit 10c21af076
7 changed files with 348 additions and 201 deletions

View file

@ -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
struct InheritFromTwo : public T, public U
{
public:
};
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
@ -131,10 +177,7 @@ 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,20 +185,14 @@ 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
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
@ -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);
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_

View file

@ -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,6 +11,10 @@ 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
// alleged illegal base class.
@ -50,9 +58,9 @@ 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,7 +108,7 @@ 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>
{
};
@ -121,7 +129,7 @@ namespace Loki
template<> struct Wrapper_VC<true>
{ template<class X> struct In; };
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
@ -139,7 +147,7 @@ namespace Loki
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;
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, V>::type type;
};
template <class Wrapper, class T, class U, class V, class W>
@ -150,8 +158,9 @@ namespace Loki
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;
Wrapper_VC< ::Loki::Private::AlwaysFalse<Wrapper>::value>::template In<T, U, V, W>::type type;
};
}
#endif

View file

@ -1,5 +1,6 @@
Loki VC 6.0 Port or how to produce C1001 - Internal Compiler Errors
-------------------------------------------------------------------
Version: 0.3
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.
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,7 +64,6 @@ 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.
@ -88,6 +114,29 @@ 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
@ -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
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.
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:
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&);
Foo(const Foo&)
{}
template <class U>
Foo(const Foo<U>&);
Foo(const Foo<U>& r)
{}
};
[/code]
Under MSVC 6.0 the above code becomes:
you *need* to write:
[code]
template <class T>
struct Foo
{
template <class U>
Foo(const Foo<U>&);
Foo(const Foo<U>& r)
{}
// copy-ctor for Foos with equal T
// not valid c++
template <>
Foo(const Foo&);
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:
------------------
@ -180,6 +252,44 @@ Interface changes:
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.

View file

@ -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,18 +92,15 @@ 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)
DefaultSPStorage(const DefaultSPStorage&)
{}
#endif
// 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>&)
{}
#if _MSC_VER <= 1200
template <>
DefaultSPStorage(const DefaultSPStorage<U>&) {}
DefaultSPStorage(const DefaultSPStorage&)
{}
#endif
DefaultSPStorage(const StoredType& p) : pointee_(p) {}
PointerType operator->() const { return pointee_; }
@ -166,11 +162,8 @@ namespace Loki
*pCount_ = 1;
}
#if !defined(_MSC_VER)
RefCounted(const RefCounted& rhs)
: pCount_(rhs.pCount_)
{}
#endif
// 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>
@ -178,12 +171,10 @@ namespace Loki
: 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_;
@ -977,10 +968,8 @@ 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,28 +994,15 @@ 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
// 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,
@ -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);

View file

@ -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_);
}

View file

@ -37,6 +37,7 @@ namespace Loki
template <int v>
struct Int2Type
{
Int2Type() {}
enum { value = v };
};

View file

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