📄 readme.txt
字号:
[/code]
becomes:
[code]
namespace Private
{
template <class R> struct FooBase
{
R Func() {return R();}
};
struct FooVoidBase
{
typedef void R;
R Func() {}
};
}
template <class R>
struct Foo : public Select<IsVoid<R>::value, FooVoidBase, FooBase<R> >::Result
{};
[/code]
The MSVC 6 allows explicit template specialization in class scope.
In contrast the C++ Standards only allows explicit template specialization
in namespace scope. Using the non-compliant feature, the implementation
of the example above becomes a little less complicated:
[code]
namespace Private
{
struct FooBase
{
template <class R>
struct In
{
R Func() {return R();}
};
template <>
struct In<void>
{;
void Func() {}
};
};
}
template <class R>
struct Foo : Private::FooBase::In<R>
{};
[/code]
Please note that *all* new base classes are only meant as a hidden
implementation detail.
You should never use any of them directly or indirectly. In particular don't
make use of the possible derived-to-base conversion.
In the old version of Functor.h I changed a ResultType of type void to
VoidAsType (an udt). This change is transparent to the user of Functor.
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)
{}
Foo(const Foo& r)
{}
};
[/code]
Many thanks to Nelson El骾 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骾'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'.
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.
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
type and ThreadingModel its current ThreadingModel.
4. TypeTraits.h
* Because VC 6.0 lacks partial template specialization, the TypeTraits-Class
fails to provide the following typedefs:
PointeeType, ReferredType, NonVolatileType and UnqualifiedType.
* Since the VC 6 does not differentiate
between void, const void, volatile void and const volatile void the following
assertions will fail:
assert(TypeTraits<const void>::isConst == 1)
assert(TypeTraits<volatile void>::isVolatile == 1)
assert(TypeTraits<const volatile void>::isConst == 1)
assert(TypeTraits<const volatile void>::isVolatile == 1)
* This port adds isEnum, isMemberFunctionPointer and isFunctionPointer.
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.
See Notes (section C) for the description of the workaround.
I also 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.
consequences:
This change will only break new Policies when switching to the
original library.
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
concrete Factory-Unit.
* Added a dummy-Parameter to AbstractFactory::Create (see C.)
Calling syntax changed from:
ConcProduct* p = aFactory.Create<ConcProduct>();
to
ConcProduct* p = aFactory.Create(Type2Type<ConcProduct>());
8. SmartPtr.h
* no template template parameters.
(see 7.for a description of the consequences)
* This port does not specialize std::less
Update:
-------
The port provides some helper-macros for convenient specialization
of std::less for Smart-Pointers.
If, for example, you want to use a Smart-Pointer as the key of a std::map,
you can do it like this:
[code]
#include <map>
#include <loki/SmartPtr.h>
SMARTPTR_SPECIALIZE_LESS(Apple)
class Apple {};
int main()
{
std::map<SmartPointer<Apple>, int> m;
//...
}
[/code]
9. Visitor.h
* 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
a set of complete new classes (and macros) for void. Default arguments of type void
were replaced by arguments of type int.
Update:
-------
In the new version of Visitor.h there are no longer extra classes for void.
Instead the original classes are now able to handle the return type void.
However there are still two sets of macros. One for return type = void
(DEFINE_VISITABLE_VOID, DEFINE_CYCLIC_VISITABLE_VOID) and one for return
type != void (DEFINE_VISITABLE, DEFINE_CYCLIC_VISITABLE)
10. MultiMethods.h
* replaced all template template parameters with 'normal' parameters (see 7.
for a description of the consequences)
* This port does not support functions with return type void.
* dummy parameters were added to functions that otherwise would depend on
explicit template argument specification (14.8.1).
Update:
-------
* The port now supports functions with return type void.
Some words to BasicDispatcher:
------------------------------
You can't use a (namespace level) template function as callback-function
for BasicDispatcher. This is because using the VC 6.0 you can't explicity
specify the template-paramters when adding the concrete function instance
to the dispatcher.
Normaly you can write something like this:
[code]
template <class DerivedShape1, class DerivedShape2>
int HatchShapes(Shape&, Shape&) {...}
typedef ::Loki::BasicDispatcher<Shape> Dispatcher;
void Func(Dispatcher& x)
{
x.Add(&HatchShapes<Circle, Rectangle>);
}
[/code]
Using the VC 6.0 this is not possible, because there is no
way to specify the types for DerivedShape1 and DerivedShape2 (at least
I know of no way).
As a workaround use a helper-template class in conjunction with
a static member function:
[code]
template <class DerivedShape1, class DerivedShape2>
struct Hatch_Helper
{
int HatchShapes(Shape&, Shape&) {...}
};
typedef ::Loki::BasicDispatcher<Shape> Dispatcher;
void Func(Dispatcher& x)
{
x.Add(&Hatch_Helper<Circle, Rectangle>::HatchShapes);
}
[/code]
Some words to FnDispatcher:
---------------------------
The trampoline-Versions of FnDispatcher::Add differ
from the original library.
Using the original library one writes:
[code]
typedef FnDispatcher<Shape> Dispatcher;
void Hatch(Rectangle& lhs, Poly& rhs) {...}
Dispatcher dis;
disp.Add<Rectangle, Poly, &Hatch>();
[/code]
Using this port the last line either becomes:
[code]
disp.Add(Dispatcher::Etas<Rectangle, Poly, &Hatch>());
[/code]
or
[code]
Dispatcher::AddI<Rectangle, Poly, &Hatch>()(dis);
[/code]
More info:
----------
The original Loki library can be found here: http://moderncppdesign.com
For Rani Sharoni's VC 7.0 port see: http://www.geocities.com/rani_sharoni/LokiPort.html
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -