From f9fa5fbbd96716a760a00a2de66594ec53336c4e Mon Sep 17 00:00:00 2001 From: magmaikh Date: Sun, 11 Aug 2002 05:41:23 +0000 Subject: [PATCH] Partial ports to MSVC 6 & 7 git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@29 7ec92016-0320-0410-acc4-a06ded1c099a --- MSVC/1200/TypeList.h | 789 ++++++++++++++++++++++++++++++++++++++ MSVC/1200/TypeManip.h | 268 +++++++++++++ MSVC/1200/TypeTraits.h | 374 ++++++++++++++++++ MSVC/1200/portby.txt | 2 + MSVC/1300/NullType.h | 37 ++ MSVC/1300/TypeInfo.h | 119 ++++++ MSVC/1300/TypeList.h | 806 +++++++++++++++++++++++++++++++++++++++ MSVC/1300/TypeManip.h | 268 +++++++++++++ MSVC/1300/TypeTraits.h | 374 ++++++++++++++++++ MSVC/1300/portby.txt | 3 + MSVC/1300/static_check.h | 51 +++ 11 files changed, 3091 insertions(+) create mode 100644 MSVC/1200/TypeList.h create mode 100644 MSVC/1200/TypeManip.h create mode 100644 MSVC/1200/TypeTraits.h create mode 100644 MSVC/1200/portby.txt create mode 100644 MSVC/1300/NullType.h create mode 100644 MSVC/1300/TypeInfo.h create mode 100644 MSVC/1300/TypeList.h create mode 100644 MSVC/1300/TypeManip.h create mode 100644 MSVC/1300/TypeTraits.h create mode 100644 MSVC/1300/portby.txt create mode 100644 MSVC/1300/static_check.h diff --git a/MSVC/1200/TypeList.h b/MSVC/1200/TypeList.h new file mode 100644 index 0000000..040ce98 --- /dev/null +++ b/MSVC/1200/TypeList.h @@ -0,0 +1,789 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: August 22, 2001 + +#ifndef TYPELIST_INC_ +#define TYPELIST_INC_ + +#include "NullType.h" +#include "TypeManip.h" + +//////////////////////////////////////////////////////////////////////////////// +// macros TYPELIST_1, TYPELIST_2, ... TYPELIST_50 +// Each takes a number of arguments equal to its numeric suffix +// The arguments are type names. TYPELIST_NN generates a typelist containing +// all types passed as arguments, in that order. +// Example: TYPELIST_2(char, int) generates a type containing char and int. +//////////////////////////////////////////////////////////////////////////////// + +#define TYPELIST_1(T1) ::Loki::Typelist + +#define TYPELIST_2(T1, T2) ::Loki::Typelist + +#define TYPELIST_3(T1, T2, T3) ::Loki::Typelist + +#define TYPELIST_4(T1, T2, T3, T4) \ + ::Loki::Typelist + +#define TYPELIST_5(T1, T2, T3, T4, T5) \ + ::Loki::Typelist + +#define TYPELIST_6(T1, T2, T3, T4, T5, T6) \ + ::Loki::Typelist + +#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ + ::Loki::Typelist + +#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ + ::Loki::Typelist + +#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ + ::Loki::Typelist + +#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ + ::Loki::Typelist + +#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \ + ::Loki::Typelist + +#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \ + ::Loki::Typelist + +#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \ + ::Loki::Typelist + +#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14) \ + ::Loki::Typelist + +#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15) \ + ::Loki::Typelist + +#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16) \ + ::Loki::Typelist + +#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17) \ + ::Loki::Typelist + +#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18) \ + ::Loki::Typelist + +#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19) \ + ::Loki::Typelist + +#define TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \ + ::Loki::Typelist + +#define TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \ + ::Loki::Typelist + +#define TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \ + ::Loki::Typelist + +#define TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \ + ::Loki::Typelist + +#define TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \ + ::Loki::Typelist + +#define TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \ + ::Loki::Typelist + +#define TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26) \ + ::Loki::Typelist + +#define TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27) \ + ::Loki::Typelist + +#define TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28) \ + ::Loki::Typelist + +#define TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29) \ + ::Loki::Typelist + +#define TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \ + ::Loki::Typelist + +#define TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \ + ::Loki::Typelist + +#define TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \ + ::Loki::Typelist + +#define TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \ + ::Loki::Typelist + +#define TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \ + ::Loki::Typelist + +#define TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35) \ + ::Loki::Typelist + +#define TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36) \ + ::Loki::Typelist + +#define TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37) \ + ::Loki::Typelist + +#define TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38) \ + ::Loki::Typelist + +#define TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39) \ + ::Loki::Typelist + +#define TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \ + ::Loki::Typelist + +#define TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \ + ::Loki::Typelist + +#define TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \ + ::Loki::Typelist + +#define TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \ + ::Loki::Typelist + +#define TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \ + ::Loki::Typelist + +#define TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45) \ + ::Loki::Typelist + +#define TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46) \ + ::Loki::Typelist + +#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47) \ + ::Loki::Typelist + +#define TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48) \ + ::Loki::Typelist + +#define TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49) \ + ::Loki::Typelist + +#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \ + ::Loki::Typelist + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template Typelist +// The building block of typelists of any length +// Use it through the TYPELIST_NN macros +// Defines nested types: +// Head (first element, a non-typelist type by convention) +// Tail (second element, can be another typelist) +//////////////////////////////////////////////////////////////////////////////// + + template + struct Typelist + { + typedef T Head; + typedef U Tail; + }; + + namespace TL + { +//////////////////////////////////////////////////////////////////////////////// +// class template Length +// Computes the length of a typelist +// Invocation (TList is a typelist): +// Length::value +// returns a compile-time constant containing the length of TList, not counting +// the end terminator (which by convention is NullType) +//////////////////////////////////////////////////////////////////////////////// + + template struct Length; + template <> struct Length + { + enum { value = 0 }; + }; + + template + struct Length + { + enum { value = 1 + Length::value }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAt +// Finds the type at a given index in a typelist +// Invocation (TList is a typelist and index is a compile-time integral +// constant): +// TypeAt::Result +// returns the type in position 'index' in TList +// If you pass an out-of-bounds index, the result is a compile-time error +//////////////////////////////////////////////////////////////////////////////// + + namespace TypeAt_ { + + template + struct Index { + template + struct Which { + typedef typename Index::Which::Result Result; + }; + }; + + template<> + struct Index<0> { + template + struct Which { + typedef typename TList::Head Result; + }; + }; + + } // namespace TypeAt_ + + template + struct TypeAt { + typedef typename TypeAt_::Index::Which::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAtNonStrict +// Finds the type at a given index in a typelist +// Invocations (TList is a typelist and index is a compile-time integral +// constant): +// a) TypeAt::Result +// returns the type in position 'index' in TList, or NullType if index is +// out-of-bounds +// b) TypeAt::Result +// returns the type in position 'index' in TList, or D if index is out-of-bounds +//////////////////////////////////////////////////////////////////////////////// + + namespace TypeAtNonStrict_ { + + template + struct ListType; + + template + struct Index; + + template<> + struct ListType { + template + struct Remainder { + typedef DefaultType Result; + }; + }; + + template<> + struct Index<0> { + template + struct Remainder { + typedef typename TList::Head Result; + }; + }; + + template + struct Index { + template + struct Remainder { + enum { isSameType = Conversion::sameType }; + typedef typename Select::Remainder::Result>::Result Result; + }; + }; + + template + struct ListType { + template + struct Remainder { + typedef typename Index::Remainder::Result Result; + }; + }; + + } // namespace TypeAtNonStrict_ + + template + struct TypeAtNonStrict { + typedef typename TypeAtNonStrict_::ListType::Remainder::Result Result; + }; + +} // namespace TL + +//////////////////////////////////////////////////////////////////////////////// +// class template IndexOf +// Finds the index of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// IndexOf::value +// returns the position of T in TList, or NullType if T is not found in TList +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace IndexOf_ { + +template +struct Head { + typedef typename TList::Head Result; +}; + +template<> +struct Head { + typedef void Result; +}; + +struct IsNull { + enum { value = -1 }; +}; + +struct IsTHead { + enum { value = 0 }; +}; + +template +struct IsNotTHead { + typedef typename TList::Tail Tail; + typedef typename Select::result, + IsNull, + typename Select::Result, T>::result, + IsTHead, IsNotTHead + >::Result + >::Result chooser; + enum { temp = chooser::value }; + enum { value = temp == -1 ? -1 : 1 + temp }; +}; + +template +struct IsNotNull { + typedef typename Select::result, + IsTHead, + IsNotTHead + >::Result chooser; + enum { value = chooser::value }; +}; + +} // namespace IndexOf_ + +} // namespace Private + +namespace TL { + +template +struct IndexOf { +private: + typedef typename Select::result, + Private::IndexOf_::IsNull, + Private::IndexOf_::IsNotNull + >::Result chooser; +public: + enum { value = chooser::value }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template Append +// Appends a type or a typelist to another +// Invocation (TList is a typelist and T is either a type or a typelist): +// Append::Result +// returns a typelist that is TList followed by T and NullType-terminated +//////////////////////////////////////////////////////////////////////////////// + + namespace Append_ { + + template + struct Helper { + struct big { char i[2]; }; + template + static char Test(const Typelist&); + static big Test(...); + static T makeT(); + }; + + } // namespace Append_ + + template + struct Append; + + template<> + struct Append { + typedef NullType Result; + }; + + template + struct Append { + private: + enum { T_is_list = sizeof(Append_::Helper::Test(Append_::Helper::MakeT())) == sizeof(char) }; + enum { TList_is_null = Conversion::sameType }; + typedef typename Select::Result Result1; + typedef typename Select, Result1>::Result Result2; + public: + typedef typename Select::Result>, Result2>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Erase +// Erases the first occurence, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// Erase::Result +// returns a typelist that is TList without the first occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template + struct Erase { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template EraseAll +// Erases all first occurences, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// EraseAll::Result +// returns a typelist that is TList without any occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template + struct EraseAll { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDuplicates +// Removes all duplicate types in a typelist +// Invocation (TList is a typelist): +// NoDuplicates::Result +//////////////////////////////////////////////////////////////////////////////// + + template + struct NoDuplicates; + + template<> + struct NoDuplicates { + typedef NullType Result; + }; + + template + struct NoDuplicates { + private: + typedef typename NoDuplicates::Result L1; + typedef typename Erase::Result L2; + public: + typedef Typelist Result; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template Replace +// Replaces the first occurence of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which the first occurence of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template + struct Replace { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ReplaceAll +// Replaces all occurences of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which all occurences of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template + struct ReplaceAll { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result>, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Reverse +// Reverses a typelist +// Invocation (TList is a typelist): +// Reverse::Result +// returns a typelist that is TList reversed +//////////////////////////////////////////////////////////////////////////////// + + template + struct Reverse { + private: + enum { list_of_one = Conversion::sameType }; + public: + typedef typename Select::Result, + typename TList::Head + >::Result + >::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template MostDerived +// Finds the type in a typelist that is the most derived from a given type +// Invocation (TList is a typelist, T is a type): +// Replace::Result +// returns the type in TList that's the most derived from T +//////////////////////////////////////////////////////////////////////////////// + + template + struct MostDerived { + private: + enum { TList_is_null = Conversion::sameType }; + typedef typename Select::Result>::Result Candidate; + public: + typedef typename Select::Result + >::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DerivedToFront +// Arranges the types in a typelist so that the most derived types appear first +// Invocation (TList is a typelist): +// DerivedToFront::Result +// returns the reordered TList +//////////////////////////////////////////////////////////////////////////////// + + namespace DerivedToFront_ { + + template + struct ListType { + }; + + template<> + struct ListType { + typedef NullType Result; + }; + + } // namespace DerivedToFront_ + + template + struct DerivedToFront; + + template<> + struct DerivedToFront { + typedef NullType Result; + }; + + template + struct DerivedToFront { + private: + typedef typename MostDerived::Result TheMostDerived; + typedef typename Replace::Result L; + public: + typedef Typelist Result; + }; + + } // namespace TL + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27 +// (credit due to Dave Taylor) +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPELIST_INC_ + diff --git a/MSVC/1200/TypeManip.h b/MSVC/1200/TypeManip.h new file mode 100644 index 0000000..2392d94 --- /dev/null +++ b/MSVC/1200/TypeManip.h @@ -0,0 +1,268 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: August 22, 2001 + +#ifndef TYPEMANIP_INC_ +#define TYPEMANIP_INC_ + +namespace Loki { + + namespace Private { + + struct big { char c[2]; }; + + struct any { + template + any(const T&); + }; + + } // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template Int2Type +// Converts each integral constant into a unique type +// Invocation: Int2Type where v is a compile-time constant integral +// Defines 'value', an enum that evaluates to v +//////////////////////////////////////////////////////////////////////////////// + + template + struct Int2Type + { + enum { value = v }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Type2Type +// Converts each type into a unique, insipid type +// Invocation Type2Type where T is a type +// Defines the type OriginalType which maps back to T +//////////////////////////////////////////////////////////////////////////////// + + template + struct Type2Type + { + typedef T OriginalType; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Select +// Selects one of two types based upon a boolean constant +// Invocation: Select::Result +// where: +// flag is a compile-time boolean constant +// T and U are types +// Result evaluates to T if flag is true, and to U otherwise. +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace Select_ { + +struct ChooseT { + template + struct Choose { + typedef T Result; + }; +}; + +struct ChooseU { + template + struct Choose { + typedef U Result; + }; +}; + +template +struct Selector { + typedef ChooseT Result; +}; + +template<> +struct Selector { + typedef ChooseU Result; +}; + +} // namespace Select_ + +} // namespace Private + +template +struct Select { +private: + typedef typename Private::Select_::Selector::Result selector; +public: + typedef typename selector::Choose::Result Result; +}; + +namespace Private { + +template +struct is_void { + enum { value = 0 }; +}; + +template<> +struct is_void { + enum { value = 1 }; +}; + +namespace is_same_ { + +template +char test_same(T*, T*); + +template +big test_same(T*, any); + +template +struct is_same_imp { + static T t; + static U u; + enum { result = sizeof(test_same(&t, &u)) == sizeof(char) }; +}; + +} // namespace is_same_ + +template +struct is_same { + enum { voidT = is_void::value }; + enum { voidU = is_void::value }; + struct BothVoid { + enum { result = 1 }; + }; + struct OneVoid { + enum { result = 0 }; + }; + typedef typename Select + >::Result + >::Result tester; + enum { result = tester::result }; +}; + +} // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template Conversion +// Figures out the conversion relationships between two types +// Invocations (T and U are types): +// a) Conversion::exists +// returns (at compile time) true if there is an implicit conversion from T +// to U (example: Derived to Base) +// b) Conversion::exists2Way +// returns (at compile time) true if there are both conversions from T +// to U and from U to T (example: int to char and back) +// c) Conversion::sameType +// returns (at compile time) true if T and U represent the same type +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace Conversion_ { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4181) +#pragma warning(disable:4800) +#pragma warning(disable:4244) +#endif +template +struct Determine { + template + struct tester { + static char test(X, Y); + static big test(any, any); + }; + static T t; + static U u; + enum { exists = sizeof(tester::test(t, t)) == sizeof(char) }; + enum { exists2Way = exists & (sizeof(tester::test(u, u)) == sizeof(char)) }; + enum { sameType = exists2Way & is_same::result }; +}; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +} // namespace Conversion_ + +} // namespace Private + +template +struct Conversion { +private: + enum { voidT = Private::is_void::value }; + enum { voidU = Private::is_void::value }; + + struct both_void { + enum { exists = 1, exists2Way = 1, sameType = 1 }; + }; + + struct one_void { + enum { exists = 1, exists2Way = 0, sameType = 0 }; + }; + + typedef typename Select + >::Result + >::Result Chooser; +public: + enum { exists = Chooser::exists }; + enum { exists2Way = Chooser::exists2Way }; + enum { sameType = Chooser::sameType }; +}; + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D, or if B and D are aliases of the +// same type. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +#define SUPERSUBCLASS(T, U) \ + (::Loki::Conversion::exists && \ + !::Loki::Conversion::sameType) + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +#define SUPERSUBCLASS_STRICT(T, U) \ + (SUPERSUBCLASS(T, U) && \ + !::Loki::Conversion::sameType) + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPEMANIP_INC_ diff --git a/MSVC/1200/TypeTraits.h b/MSVC/1200/TypeTraits.h new file mode 100644 index 0000000..4ff198c --- /dev/null +++ b/MSVC/1200/TypeTraits.h @@ -0,0 +1,374 @@ +#ifndef TYPETRAITS_INC_ +#define TYPETRAITS_INC_ + +#include "Typelist.h" + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomUnsignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomUnsignedInt where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomUnsignedInt + { + enum { value = 0 }; + }; + +#ifdef _MSC_VER + template<> + struct IsCustomUnsignedInt { + enum { value = 1 }; + }; +#endif + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomSignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomSignedInt where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in signed +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomSignedInt + { + enum { value = 0 }; + }; + +#ifdef _MSC_VER + template<> + struct IsCustomSignedInt<__int64> { + enum { value = 1 }; + }; +#endif + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomFloat +// Offers a means to integrate nonstandard floating point types with the +// TypeTraits class template defined below. +// Invocation: IsCustomFloat where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in +// floating point type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomFloat + { + enum { value = 0 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// Helper types for class template TypeTraits defined below +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + typedef TYPELIST_4(unsigned char, unsigned short int, + unsigned int, unsigned long int) StdUnsignedInts; + typedef TYPELIST_4(signed char, short int, + int, long int) StdSignedInts; + typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts; + typedef TYPELIST_3(float, double, long double) StdFloats; + + char test_ptr(const volatile void*, const volatile void*); + big test_ptr(any, any); + + template + T* unrefptr(T&); + + char test_const(const volatile void*); + big test_const(volatile void*); + char test_volatile(const volatile void*); + big test_volatile(const void*); + + template + char test_mptr(V X::*, any); + + big test_mptr(any, any); + + template + struct AddReferenceImp { + template + struct Imp { + typedef T Result; + }; + }; + + template<> + struct AddReferenceImp { + template + struct Imp { + typedef T& Result; + }; + }; + +#ifndef _MSC_VER + template struct PointerTraits + { + enum { result = false }; + typedef NullType PointeeType; + }; + + template struct PointerTraits + { + enum { result = true }; + typedef U PointeeType; + }; +#else + template + struct PointerTraits { + private: + static U u; + public: + typedef void PointeeType; // unable to determine correctly + enum { result = sizeof(Private::test_ptr(&u, u)) == sizeof(char) }; + }; + + template<> + struct PointerTraits { + typedef void PointeeType; + enum { result = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct ReferenceTraits + { + enum { result = false }; + typedef U ReferredType; + }; + + template struct ReferenceTraits + { + enum { result = true }; + typedef U ReferredType; + }; +#else +#pragma warning(push) +#pragma warning(disable:4181) + template + struct ReferenceTraits { + typedef U const volatile cv_u; + static cv_u u; + public: + enum { result = (sizeof(Private::test_const(&u)) != sizeof(char)) + | (sizeof(Private::test_volatile(&u)) != sizeof(char)) }; + typedef void ReferredType; // unable to determine correctly + }; +#pragma warning(pop) + + template<> + struct ReferenceTraits { + enum { result = 0 }; + typedef void ReferredType; + }; +#endif +#ifndef _MSC_VER + template struct PToMTraits + { + enum { result = false }; + }; + + template + struct PToMTraits + { + enum { result = true }; + }; +#else + template + struct PToMTraits { + private: + static U u; + public: + enum { result = sizeof(Private::test_mptr(u, &u)) == sizeof(char) }; + }; + + template<> + struct PToMTraits { + enum { result = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct UnConst + { + typedef U Result; + enum { isConst = 0 }; + }; + + template struct UnConst + { + typedef U Result; + enum { isConst = 1 }; + }; +#else + template + struct UnConst { + private: + static U u; + public: + typedef void Result; // unable to determine correctly + enum { isConst = sizeof(Private::test_const(Private::unrefptr(u))) == sizeof(char) }; + }; + + template<> + struct UnConst { + typedef void Result; + enum { isConst = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct UnVolatile + { + typedef U Result; + enum { isVolatile = 0 }; + }; + + template struct UnVolatile + { + typedef U Result; + enum { isVolatile = 1 }; + }; +#else + template + struct UnVolatile { + private: + static U u; + public: + typedef void Result; // unable to determine correctly + enum { isVolatile = sizeof(Private::test_volatile(Private::unrefptr(u))) == sizeof(char) }; + }; + + template<> + struct UnVolatile { + typedef void Result; + enum { isVolatile = 0 }; + }; +#endif + template + struct AddReference { + typedef typename Private::AddReferenceImp::template Imp::Result Result; + }; + + template<> + struct AddReference { + typedef void Result; + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeTraits +// Figures out various properties of any given type +// Invocations (T is a type): +// a) TypeTraits::isPointer +// returns (at compile time) true if T is a pointer type +// b) TypeTraits::PointeeType +// returns the type to which T points is T is a pointer type, NullType otherwise +// a) TypeTraits::isReference +// returns (at compile time) true if T is a reference type +// b) TypeTraits::ReferredType +// returns the type to which T refers is T is a reference type, NullType +// otherwise +// c) TypeTraits::isMemberPointer +// returns (at compile time) true if T is a pointer to member type +// d) TypeTraits::isStdUnsignedInt +// returns (at compile time) true if T is a standard unsigned integral type +// e) TypeTraits::isStdSignedInt +// returns (at compile time) true if T is a standard signed integral type +// f) TypeTraits::isStdIntegral +// returns (at compile time) true if T is a standard integral type +// g) TypeTraits::isStdFloat +// returns (at compile time) true if T is a standard floating-point type +// h) TypeTraits::isStdArith +// returns (at compile time) true if T is a standard arithmetic type +// i) TypeTraits::isStdFundamental +// returns (at compile time) true if T is a standard fundamental type +// j) TypeTraits::isUnsignedInt +// returns (at compile time) true if T is a unsigned integral type +// k) TypeTraits::isSignedInt +// returns (at compile time) true if T is a signed integral type +// l) TypeTraits::isIntegral +// returns (at compile time) true if T is a integral type +// m) TypeTraits::isFloat +// returns (at compile time) true if T is a floating-point type +// n) TypeTraits::isArith +// returns (at compile time) true if T is a arithmetic type +// o) TypeTraits::isFundamental +// returns (at compile time) true if T is a fundamental type +// p) TypeTraits::ParameterType +// returns the optimal type to be used as a parameter for functions that take Ts +// q) TypeTraits::isConst +// returns (at compile time) true if T is a const-qualified type +// r) TypeTraits::NonConstType +// removes the 'const' qualifier from T, if any +// s) TypeTraits::isVolatile +// returns (at compile time) true if T is a volatile-qualified type +// t) TypeTraits::NonVolatileType +// removes the 'volatile' qualifier from T, if any +// u) TypeTraits::UnqualifiedType +// removes both the 'const' and 'volatile' qualifiers from T, if any +//////////////////////////////////////////////////////////////////////////////// + + template + class TypeTraits + { + public: + enum { isPointer = Private::PointerTraits::result }; + typedef typename Private::PointerTraits::PointeeType PointeeType; + + enum { isReference = Private::ReferenceTraits::result }; + typedef typename Private::ReferenceTraits::ReferredType ReferredType; + + enum { isMemberPointer = Private::PToMTraits::result }; + + enum { isStdUnsignedInt = + TL::IndexOf::value >= 0 }; + enum { isStdSignedInt = + TL::IndexOf::value >= 0 }; + enum { isStdIntegral = isStdUnsignedInt || isStdSignedInt || + TL::IndexOf::value >= 0 }; + enum { isStdFloat = TL::IndexOf::value >= 0 }; + enum { isStdArith = isStdIntegral || isStdFloat }; + enum { isStdFundamental = isStdArith || isStdFloat || + Conversion::sameType }; + + enum { isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt::value }; + enum { isSignedInt = isStdSignedInt || IsCustomSignedInt::value }; + enum { isIntegral = isStdIntegral || isUnsignedInt || isSignedInt }; + enum { isFloat = isStdFloat || IsCustomFloat::value }; + enum { isArith = isIntegral || isFloat }; + enum { isFundamental = isStdFundamental || isArith || isFloat }; + + typedef typename Select::Result + >::Result ParameterType; + + enum { isConst = Private::UnConst::isConst }; + typedef typename Private::UnConst::Result NonConstType; + enum { isVolatile = Private::UnVolatile::isVolatile }; + typedef typename Private::UnVolatile::Result NonVolatileType; + typedef typename Private::UnVolatile::Result>::Result + UnqualifiedType; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPETRAITS_INC_ diff --git a/MSVC/1200/portby.txt b/MSVC/1200/portby.txt new file mode 100644 index 0000000..6836ad7 --- /dev/null +++ b/MSVC/1200/portby.txt @@ -0,0 +1,2 @@ +MSVC6 +Jonathan H. Lundquist \ No newline at end of file diff --git a/MSVC/1300/NullType.h b/MSVC/1300/NullType.h new file mode 100644 index 0000000..c599315 --- /dev/null +++ b/MSVC/1300/NullType.h @@ -0,0 +1,37 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: June 20, 2001 + +#ifndef NULLTYPE_INC_ +#define NULLTYPE_INC_ + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class NullType +// Used as a placeholder for "no type here" +// Useful as an end marker in typelists +//////////////////////////////////////////////////////////////////////////////// + + class NullType {}; +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +//////////////////////////////////////////////////////////////////////////////// + +#endif // NULLTYPE_INC_ diff --git a/MSVC/1300/TypeInfo.h b/MSVC/1300/TypeInfo.h new file mode 100644 index 0000000..1f36eb9 --- /dev/null +++ b/MSVC/1300/TypeInfo.h @@ -0,0 +1,119 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: June 20, 2001 + +// MKH +// Copy of TypeInfo.h made to that #include "Typelist.h" gets the local +// flavor instead of the reference implementation +// Added a couple of #pramga warning(disable:4800) becase we just don't care. + +#ifndef TYPEINFO_INC_ +#define TYPEINFO_INC_ + +#include +#include +#include "Typelist.h" + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class TypeInfo +// Purpose: offer a first-class, comparable wrapper over std::type_info +//////////////////////////////////////////////////////////////////////////////// + + class TypeInfo + { + public: + // Constructors + TypeInfo(); // needed for containers + TypeInfo(const std::type_info&); // non-explicit + + // Access for the wrapped std::type_info + const std::type_info& Get() const; + // Compatibility functions + bool before(const TypeInfo& rhs) const; + const char* name() const; + + private: + const std::type_info* pInfo_; + }; + +// Implementation + + inline TypeInfo::TypeInfo() + { + class Nil {}; + pInfo_ = &typeid(Nil); + assert(pInfo_); + } + + inline TypeInfo::TypeInfo(const std::type_info& ti) + : pInfo_(&ti) + { assert(pInfo_); } + + inline bool TypeInfo::before(const TypeInfo& rhs) const + { + assert(pInfo_); + #pragma warning(push) + #pragma warning(disable: 4800) + return pInfo_->before(*rhs.pInfo_); + #pragma warning(pop) + } + + inline const std::type_info& TypeInfo::Get() const + { + assert(pInfo_); + return *pInfo_; + } + + inline const char* TypeInfo::name() const + { + assert(pInfo_); + return pInfo_->name(); + } + +// Comparison operators + + inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs) + { + #pragma warning(push) + #pragma warning(disable: 4800) + return lhs.Get() == rhs.Get(); + #pragma warning(pop) + } + + inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs) + { return lhs.before(rhs); } + + inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs == rhs); } + + inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs) + { return rhs < lhs; } + + inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs > rhs); } + + inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs) + { return !(lhs < rhs); } +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPEINFO_INC_ diff --git a/MSVC/1300/TypeList.h b/MSVC/1300/TypeList.h new file mode 100644 index 0000000..cb0f45d --- /dev/null +++ b/MSVC/1300/TypeList.h @@ -0,0 +1,806 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: August 22, 2001 + +#ifndef TYPELIST_INC_ +#define TYPELIST_INC_ + +#include "NullType.h" +#include "TypeManip.h" + +//////////////////////////////////////////////////////////////////////////////// +// macros TYPELIST_1, TYPELIST_2, ... TYPELIST_50 +// Each takes a number of arguments equal to its numeric suffix +// The arguments are type names. TYPELIST_NN generates a typelist containing +// all types passed as arguments, in that order. +// Example: TYPELIST_2(char, int) generates a type containing char and int. +//////////////////////////////////////////////////////////////////////////////// + +#define TYPELIST_1(T1) ::Loki::Typelist + +#define TYPELIST_2(T1, T2) ::Loki::Typelist + +#define TYPELIST_3(T1, T2, T3) ::Loki::Typelist + +#define TYPELIST_4(T1, T2, T3, T4) \ + ::Loki::Typelist + +#define TYPELIST_5(T1, T2, T3, T4, T5) \ + ::Loki::Typelist + +#define TYPELIST_6(T1, T2, T3, T4, T5, T6) \ + ::Loki::Typelist + +#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ + ::Loki::Typelist + +#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ + ::Loki::Typelist + +#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ + ::Loki::Typelist + +#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ + ::Loki::Typelist + +#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \ + ::Loki::Typelist + +#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \ + ::Loki::Typelist + +#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \ + ::Loki::Typelist + +#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14) \ + ::Loki::Typelist + +#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15) \ + ::Loki::Typelist + +#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16) \ + ::Loki::Typelist + +#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17) \ + ::Loki::Typelist + +#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18) \ + ::Loki::Typelist + +#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19) \ + ::Loki::Typelist + +#define TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \ + ::Loki::Typelist + +#define TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \ + ::Loki::Typelist + +#define TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \ + ::Loki::Typelist + +#define TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \ + ::Loki::Typelist + +#define TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \ + ::Loki::Typelist + +#define TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \ + ::Loki::Typelist + +#define TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26) \ + ::Loki::Typelist + +#define TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27) \ + ::Loki::Typelist + +#define TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28) \ + ::Loki::Typelist + +#define TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29) \ + ::Loki::Typelist + +#define TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \ + ::Loki::Typelist + +#define TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \ + ::Loki::Typelist + +#define TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \ + ::Loki::Typelist + +#define TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \ + ::Loki::Typelist + +#define TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \ + ::Loki::Typelist + +#define TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35) \ + ::Loki::Typelist + +#define TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36) \ + ::Loki::Typelist + +#define TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37) \ + ::Loki::Typelist + +#define TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38) \ + ::Loki::Typelist + +#define TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39) \ + ::Loki::Typelist + +#define TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \ + ::Loki::Typelist + +#define TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \ + ::Loki::Typelist + +#define TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \ + ::Loki::Typelist + +#define TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \ + ::Loki::Typelist + +#define TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \ + ::Loki::Typelist + +#define TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45) \ + ::Loki::Typelist + +#define TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46) \ + ::Loki::Typelist + +#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47) \ + ::Loki::Typelist + +#define TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48) \ + ::Loki::Typelist + +#define TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49) \ + ::Loki::Typelist + +#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ + T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ + T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ + T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ + T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \ + ::Loki::Typelist + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template Typelist +// The building block of typelists of any length +// Use it through the TYPELIST_NN macros +// Defines nested types: +// Head (first element, a non-typelist type by convention) +// Tail (second element, can be another typelist) +//////////////////////////////////////////////////////////////////////////////// + + template + struct Typelist + { + typedef T Head; + typedef U Tail; + }; + + namespace TL + { +//////////////////////////////////////////////////////////////////////////////// +// class template Length +// Computes the length of a typelist +// Invocation (TList is a typelist): +// Length::value +// returns a compile-time constant containing the length of TList, not counting +// the end terminator (which by convention is NullType) +//////////////////////////////////////////////////////////////////////////////// + //* + namespace Length_ + { + template + struct HeadLength + { + enum { value = 1 }; + }; + + template <> + struct HeadLength + { + enum { value = 0 }; + }; + }//ns TL::Length_ + //*/ + template struct Length; + template <> struct Length + { + enum { value = 0 }; + }; + + template + struct Length + { + enum { value = (Length_::HeadLength::value + + + Length::value) }; + }; +//*/ +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAt +// Finds the type at a given index in a typelist +// Invocation (TList is a typelist and index is a compile-time integral +// constant): +// TypeAt::Result +// returns the type in position 'index' in TList +// If you pass an out-of-bounds index, the result is a compile-time error +//////////////////////////////////////////////////////////////////////////////// + + namespace TypeAt_ { + + template + struct Index { + template + struct Which { + typedef typename Index::Which::Result Result; + }; + }; + + template<> + struct Index<0> { + template + struct Which { + typedef typename TList::Head Result; + }; + }; + + } // namespace TypeAt_ + + template + struct TypeAt { + typedef typename TypeAt_::Index::Which::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeAtNonStrict +// Finds the type at a given index in a typelist +// Invocations (TList is a typelist and index is a compile-time integral +// constant): +// a) TypeAt::Result +// returns the type in position 'index' in TList, or NullType if index is +// out-of-bounds +// b) TypeAt::Result +// returns the type in position 'index' in TList, or D if index is out-of-bounds +//////////////////////////////////////////////////////////////////////////////// + + namespace TypeAtNonStrict_ { + + template + struct ListType; + + template + struct Index; + + template<> + struct ListType { + template + struct Remainder { + typedef DefaultType Result; + }; + }; + + template<> + struct Index<0> { + template + struct Remainder { + typedef typename TList::Head Result; + }; + }; + + template + struct Index { + template + struct Remainder { + enum { isSameType = Conversion::sameType }; + typedef typename Select::Remainder::Result>::Result Result; + }; + }; + + template + struct ListType { + template + struct Remainder { + typedef typename Index::Remainder::Result Result; + }; + }; + + } // namespace TypeAtNonStrict_ + + template + struct TypeAtNonStrict { + typedef typename TypeAtNonStrict_::ListType::Remainder::Result Result; + }; + +} // namespace TL + +//////////////////////////////////////////////////////////////////////////////// +// class template IndexOf +// Finds the index of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// IndexOf::value +// returns the position of T in TList, or NullType if T is not found in TList +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace IndexOf_ { + +template +struct Head { + typedef typename TList::Head Result; +}; + +template<> +struct Head { + typedef void Result; +}; + +struct IsNull { + enum { value = -1 }; +}; + +struct IsTHead { + enum { value = 0 }; +}; + +template +struct IsNotTHead { + typedef typename TList::Tail Tail; + typedef typename Select::result, + IsNull, + typename Select::Result, T>::result, + IsTHead, IsNotTHead + >::Result + >::Result chooser; + enum { temp = chooser::value }; + enum { value = temp == -1 ? -1 : 1 + temp }; +}; + +template +struct IsNotNull { + typedef typename Select::result, + IsTHead, + IsNotTHead + >::Result chooser; + enum { value = chooser::value }; +}; + +} // namespace IndexOf_ + +} // namespace Private + +namespace TL { + +template +struct IndexOf { +private: + typedef typename Select::result, + Private::IndexOf_::IsNull, + Private::IndexOf_::IsNotNull + >::Result chooser; +public: + enum { value = chooser::value }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// class template Append +// Appends a type or a typelist to another +// Invocation (TList is a typelist and T is either a type or a typelist): +// Append::Result +// returns a typelist that is TList followed by T and NullType-terminated +//////////////////////////////////////////////////////////////////////////////// + + namespace Append_ { + + template + struct Helper { + struct big { char i[2]; }; + template + static char Test(const Typelist&); + static big Test(...); + static T makeT(); + }; + + } // namespace Append_ + + template + struct Append; + + template<> + struct Append { + typedef NullType Result; + }; + + template + struct Append { + private: + enum { T_is_list = sizeof(Append_::Helper::Test(Append_::Helper::MakeT())) == sizeof(char) }; + enum { TList_is_null = Conversion::sameType }; + typedef typename Select::Result Result1; + typedef typename Select, Result1>::Result Result2; + public: + typedef typename Select::Result>, Result2>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Erase +// Erases the first occurence, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// Erase::Result +// returns a typelist that is TList without the first occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template + struct Erase { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template EraseAll +// Erases all first occurences, if any, of a type in a typelist +// Invocation (TList is a typelist and T is a type): +// EraseAll::Result +// returns a typelist that is TList without any occurence of T +//////////////////////////////////////////////////////////////////////////////// + + template + struct EraseAll { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template NoDuplicates +// Removes all duplicate types in a typelist +// Invocation (TList is a typelist): +// NoDuplicates::Result +//////////////////////////////////////////////////////////////////////////////// + + template + struct NoDuplicates; + + template<> + struct NoDuplicates { + typedef NullType Result; + }; + + template + struct NoDuplicates { + private: + typedef typename NoDuplicates::Result L1; + typedef typename Erase::Result L2; + public: + typedef Typelist Result; + }; + + +//////////////////////////////////////////////////////////////////////////////// +// class template Replace +// Replaces the first occurence of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which the first occurence of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template + struct Replace { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template ReplaceAll +// Replaces all occurences of a type in a typelist, with another type +// Invocation (TList is a typelist, T, U are types): +// Replace::Result +// returns a typelist in which all occurences of T is replaced with U +//////////////////////////////////////////////////////////////////////////////// + + template + struct ReplaceAll { + private: + enum { TList_is_null = Conversion::sameType }; + enum { Head_is_T = Conversion::sameType }; + typedef typename Select::Result>, NullType>::Result Result1; + public: + typedef typename Select::Result>, Result1>::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Reverse +// Reverses a typelist +// Invocation (TList is a typelist): +// Reverse::Result +// returns a typelist that is TList reversed +//////////////////////////////////////////////////////////////////////////////// + + template + struct Reverse { + private: + enum { list_of_one = Conversion::sameType }; + public: + typedef typename Select::Result, + typename TList::Head + >::Result + >::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template MostDerived +// Finds the type in a typelist that is the most derived from a given type +// Invocation (TList is a typelist, T is a type): +// Replace::Result +// returns the type in TList that's the most derived from T +//////////////////////////////////////////////////////////////////////////////// + + template + struct MostDerived { + private: + enum { TList_is_null = Conversion::sameType }; + typedef typename Select::Result>::Result Candidate; + public: + typedef typename Select::Result + >::Result Result; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template DerivedToFront +// Arranges the types in a typelist so that the most derived types appear first +// Invocation (TList is a typelist): +// DerivedToFront::Result +// returns the reordered TList +//////////////////////////////////////////////////////////////////////////////// + + namespace DerivedToFront_ { + + template + struct ListType { + }; + + template<> + struct ListType { + typedef NullType Result; + }; + + } // namespace DerivedToFront_ + + template + struct DerivedToFront; + + template<> + struct DerivedToFront { + typedef NullType Result; + }; + + template + struct DerivedToFront { + private: + typedef typename MostDerived::Result TheMostDerived; + typedef typename Replace::Result L; + public: + typedef Typelist Result; + }; + + } // namespace TL + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27 +// (credit due to Dave Taylor) +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPELIST_INC_ + diff --git a/MSVC/1300/TypeManip.h b/MSVC/1300/TypeManip.h new file mode 100644 index 0000000..85447e6 --- /dev/null +++ b/MSVC/1300/TypeManip.h @@ -0,0 +1,268 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: August 22, 2001 + +#ifndef TYPEMANIP_INC_ +#define TYPEMANIP_INC_ + +namespace Loki { + + namespace Private { + + struct big { char c[2]; }; + + struct any { + template + any(const T&); + }; + + } // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template Int2Type +// Converts each integral constant into a unique type +// Invocation: Int2Type where v is a compile-time constant integral +// Defines 'value', an enum that evaluates to v +//////////////////////////////////////////////////////////////////////////////// + + template + struct Int2Type + { + enum { value = v }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Type2Type +// Converts each type into a unique, insipid type +// Invocation Type2Type where T is a type +// Defines the type OriginalType which maps back to T +//////////////////////////////////////////////////////////////////////////////// + + template + struct Type2Type + { + typedef T OriginalType; + }; + +//////////////////////////////////////////////////////////////////////////////// +// class template Select +// Selects one of two types based upon a boolean constant +// Invocation: Select::Result +// where: +// flag is a compile-time boolean constant +// T and U are types +// Result evaluates to T if flag is true, and to U otherwise. +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace Select_ { + +struct ChooseT { + template + struct Choose { + typedef T Result; + }; +}; + +struct ChooseU { + template + struct Choose { + typedef U Result; + }; +}; + +template +struct Selector { + typedef ChooseT Result; +}; + +template<> +struct Selector { + typedef ChooseU Result; +}; + +} // namespace Select_ + +} // namespace Private + +template +struct Select { +private: + typedef typename Private::Select_::Selector::Result selector; +public: + typedef typename selector::Choose::Result Result; +}; + +namespace Private { + +template +struct is_void { + enum { value = 0 }; +}; + +template<> +struct is_void { + enum { value = 1 }; +}; + +namespace is_same_ { + +template +char test_same(T*, T*); + +template +big test_same(T*, any); + +template +struct is_same_imp { + static T t; + static U u; + enum { result = sizeof(test_same(&t, &u)) == sizeof(char) }; +}; + +} // namespace is_same_ + +template +struct is_same { + enum { voidT = is_void::value }; + enum { voidU = is_void::value }; + struct BothVoid { + enum { result = 1 }; + }; + struct OneVoid { + enum { result = 0 }; + }; + typedef typename Select + >::Result + >::Result tester; + enum { result = tester::result }; +}; + +} // namespace Private + +//////////////////////////////////////////////////////////////////////////////// +// class template Conversion +// Figures out the conversion relationships between two types +// Invocations (T and U are types): +// a) Conversion::exists +// returns (at compile time) true if there is an implicit conversion from T +// to U (example: Derived to Base) +// b) Conversion::exists2Way +// returns (at compile time) true if there are both conversions from T +// to U and from U to T (example: int to char and back) +// c) Conversion::sameType +// returns (at compile time) true if T and U represent the same type +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +namespace Private { + +namespace Conversion_ { + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4181) +#pragma warning(disable:4800) +#pragma warning(disable:4244) +#endif +template +struct Determine { + template + struct tester { + static char test(X, Y); + static big test(any, any); + }; + static T t; + static U u; + enum { exists = sizeof(tester::test(t, t)) == sizeof(char) }; + enum { exists2Way = exists & (sizeof(tester::test(u, u)) == sizeof(char)) }; + enum { sameType = exists2Way & is_same::result }; +}; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +} // namespace Conversion_ + +} // namespace Private + +template +struct Conversion { +private: + enum { voidT = Private::is_void::value }; + enum { voidU = Private::is_void::value }; + + struct both_void { + enum { exists = 1, exists2Way = 1, sameType = 1 }; + }; + + struct one_void { + enum { exists = 1, exists2Way = 0, sameType = 0 }; + }; + + typedef typename Select + >::Result + >::Result Chooser; +public: + enum { exists = Chooser::exists }; + enum { exists2Way = Chooser::exists2Way }; + enum { sameType = Chooser::sameType }; +}; + +} // namespace Loki + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D, or if B and D are aliases of the +// same type. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +#define SUPERSUBCLASS(T, U) \ + (::Loki::Conversion::exists && \ + !::Loki::Conversion::sameType) + +//////////////////////////////////////////////////////////////////////////////// +// macro SUPERSUBCLASS +// Invocation: SUPERSUBCLASS(B, D) where B and D are types. +// Returns true if B is a public base of D. +// +// Caveat: might not work if T and U are in a private inheritance hierarchy. +//////////////////////////////////////////////////////////////////////////////// + +#define SUPERSUBCLASS_STRICT(T, U) \ + (SUPERSUBCLASS(T, U) && \ + !::Loki::Conversion::sameType) + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC6 +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPEMANIP_INC_ diff --git a/MSVC/1300/TypeTraits.h b/MSVC/1300/TypeTraits.h new file mode 100644 index 0000000..329696e --- /dev/null +++ b/MSVC/1300/TypeTraits.h @@ -0,0 +1,374 @@ +#ifndef TYPETRAITS_INC_ +#define TYPETRAITS_INC_ + +#include "Typelist.h" + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomUnsignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomUnsignedInt where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomUnsignedInt + { + enum { value = 0 }; + }; + +#ifdef _MSC_VER + template<> + struct IsCustomUnsignedInt { + enum { value = 1 }; + }; +#endif + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomSignedInt +// Offers a means to integrate nonstandard built-in unsigned integral types +// (such as unsigned __int64 or unsigned long long int) with the TypeTraits +// class template defined below. +// Invocation: IsCustomSignedInt where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in signed +// integral type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomSignedInt + { + enum { value = 0 }; + }; + +#ifdef _MSC_VER + template<> + struct IsCustomSignedInt<__int64> { + enum { value = 1 }; + }; +#endif + +//////////////////////////////////////////////////////////////////////////////// +// class template IsCustomFloat +// Offers a means to integrate nonstandard floating point types with the +// TypeTraits class template defined below. +// Invocation: IsCustomFloat where T is any type +// Defines 'value', an enum that is 1 iff T is a custom built-in +// floating point type +// Specialize this class template for nonstandard unsigned integral types +// and define value = 1 in those specializations +//////////////////////////////////////////////////////////////////////////////// + + template + struct IsCustomFloat + { + enum { value = 0 }; + }; + +//////////////////////////////////////////////////////////////////////////////// +// Helper types for class template TypeTraits defined below +//////////////////////////////////////////////////////////////////////////////// + + namespace Private + { + typedef TYPELIST_4(unsigned char, unsigned short int, + unsigned int, unsigned long int) StdUnsignedInts; + typedef TYPELIST_4(signed char, short int, + int, long int) StdSignedInts; + typedef TYPELIST_3(bool, char, wchar_t) StdOtherInts; + typedef TYPELIST_3(float, double, long double) StdFloats; + + char test_ptr(const volatile void*, const volatile void*); + big test_ptr(any, any); + + template + T* unrefptr(T&); + + char test_const(const volatile void*); + big test_const(volatile void*); + char test_volatile(const volatile void*); + big test_volatile(const void*); + + template + char test_mptr(V X::*, any); + + big test_mptr(any, any); + + template + struct AddReferenceImp { + template + struct Imp { + typedef T Result; + }; + }; + + template<> + struct AddReferenceImp { + template + struct Imp { + typedef T& Result; + }; + }; + +#ifndef _MSC_VER + template struct PointerTraits + { + enum { result = false }; + typedef NullType PointeeType; + }; + + template struct PointerTraits + { + enum { result = true }; + typedef U PointeeType; + }; +#else + template + struct PointerTraits { + private: + static U u; + public: + typedef void PointeeType; // unable to determine correctly + enum { result = sizeof(Private::test_ptr(&u, u)) == sizeof(char) }; + }; + + template<> + struct PointerTraits { + typedef void PointeeType; + enum { result = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct ReferenceTraits + { + enum { result = false }; + typedef U ReferredType; + }; + + template struct ReferenceTraits + { + enum { result = true }; + typedef U ReferredType; + }; +#else +#pragma warning(push) +#pragma warning(disable:4181) + template + struct ReferenceTraits { + typedef U const volatile cv_u; + static cv_u u; + public: + enum { result = (sizeof(Private::test_const(&u)) != sizeof(char)) + | (sizeof(Private::test_volatile(&u)) != sizeof(char)) }; + typedef void ReferredType; // unable to determine correctly + }; +#pragma warning(pop) + + template<> + struct ReferenceTraits { + enum { result = 0 }; + typedef void ReferredType; + }; +#endif +#ifndef _MSC_VER + template struct PToMTraits + { + enum { result = false }; + }; + + template + struct PToMTraits + { + enum { result = true }; + }; +#else + template + struct PToMTraits { + private: + static U u; + public: + enum { result = sizeof(Private::test_mptr(u, &u)) == sizeof(char) }; + }; + + template<> + struct PToMTraits { + enum { result = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct UnConst + { + typedef U Result; + enum { isConst = 0 }; + }; + + template struct UnConst + { + typedef U Result; + enum { isConst = 1 }; + }; +#else + template + struct UnConst { + private: + static U u; + public: + typedef void Result; // unable to determine correctly + enum { isConst = sizeof(Private::test_const(Private::unrefptr(u))) == sizeof(char) }; + }; + + template<> + struct UnConst { + typedef void Result; + enum { isConst = 0 }; + }; +#endif +#ifndef _MSC_VER + template struct UnVolatile + { + typedef U Result; + enum { isVolatile = 0 }; + }; + + template struct UnVolatile + { + typedef U Result; + enum { isVolatile = 1 }; + }; +#else + template + struct UnVolatile { + private: + static U u; + public: + typedef void Result; // unable to determine correctly + enum { isVolatile = sizeof(Private::test_volatile(Private::unrefptr(u))) == sizeof(char) }; + }; + + template<> + struct UnVolatile { + typedef void Result; + enum { isVolatile = 0 }; + }; +#endif + template + struct AddReference { + typedef typename Private::AddReferenceImp::template Imp::Result Result; + }; + + template<> + struct AddReference { + typedef void Result; + }; + } + +//////////////////////////////////////////////////////////////////////////////// +// class template TypeTraits +// Figures out various properties of any given type +// Invocations (T is a type): +// a) TypeTraits::isPointer +// returns (at compile time) true if T is a pointer type +// b) TypeTraits::PointeeType +// returns the type to which T points is T is a pointer type, NullType otherwise +// a) TypeTraits::isReference +// returns (at compile time) true if T is a reference type +// b) TypeTraits::ReferredType +// returns the type to which T refers is T is a reference type, NullType +// otherwise +// c) TypeTraits::isMemberPointer +// returns (at compile time) true if T is a pointer to member type +// d) TypeTraits::isStdUnsignedInt +// returns (at compile time) true if T is a standard unsigned integral type +// e) TypeTraits::isStdSignedInt +// returns (at compile time) true if T is a standard signed integral type +// f) TypeTraits::isStdIntegral +// returns (at compile time) true if T is a standard integral type +// g) TypeTraits::isStdFloat +// returns (at compile time) true if T is a standard floating-point type +// h) TypeTraits::isStdArith +// returns (at compile time) true if T is a standard arithmetic type +// i) TypeTraits::isStdFundamental +// returns (at compile time) true if T is a standard fundamental type +// j) TypeTraits::isUnsignedInt +// returns (at compile time) true if T is a unsigned integral type +// k) TypeTraits::isSignedInt +// returns (at compile time) true if T is a signed integral type +// l) TypeTraits::isIntegral +// returns (at compile time) true if T is a integral type +// m) TypeTraits::isFloat +// returns (at compile time) true if T is a floating-point type +// n) TypeTraits::isArith +// returns (at compile time) true if T is a arithmetic type +// o) TypeTraits::isFundamental +// returns (at compile time) true if T is a fundamental type +// p) TypeTraits::ParameterType +// returns the optimal type to be used as a parameter for functions that take Ts +// q) TypeTraits::isConst +// returns (at compile time) true if T is a const-qualified type +// r) TypeTraits::NonConstType +// removes the 'const' qualifier from T, if any +// s) TypeTraits::isVolatile +// returns (at compile time) true if T is a volatile-qualified type +// t) TypeTraits::NonVolatileType +// removes the 'volatile' qualifier from T, if any +// u) TypeTraits::UnqualifiedType +// removes both the 'const' and 'volatile' qualifiers from T, if any +//////////////////////////////////////////////////////////////////////////////// + + template + class TypeTraits + { + public: + static const isPointer = Private::PointerTraits::result; + //enum { isPointer = Private::PointerTraits::result }; + typedef typename Private::PointerTraits::PointeeType PointeeType; + static const isReference = Private::ReferenceTraits::result; + typedef typename Private::ReferenceTraits::ReferredType ReferredType; + + static const isMemberPointer = Private::PToMTraits::result; + + static const isStdUnsignedInt = + TL::IndexOf::value >= 0; + static const isStdSignedInt = + TL::IndexOf::value >= 0; + static const isStdIntegral = isStdUnsignedInt || isStdSignedInt || + TL::IndexOf::value >= 0; + static const isStdFloat = TL::IndexOf::value >= 0; + static const isStdArith = isStdIntegral || isStdFloat; + static const isStdFundamental = isStdArith || isStdFloat || + Conversion::sameType; + + static const isUnsignedInt = isStdUnsignedInt || IsCustomUnsignedInt::value; + static const isSignedInt = isStdSignedInt || IsCustomSignedInt::value; + static const isIntegral = isStdIntegral || isUnsignedInt || isSignedInt; + static const isFloat = isStdFloat || IsCustomFloat::value; + static const isArith = isIntegral || isFloat; + static const isFundamental = isStdFundamental || isArith || isFloat; + + typedef typename Select::Result + >::Result ParameterType; + + static const isConst = Private::UnConst::isConst; + typedef typename Private::UnConst::Result NonConstType; + static const isVolatile = Private::UnVolatile::isVolatile; + typedef typename Private::UnVolatile::Result NonVolatileType; + typedef typename Private::UnVolatile::Result>::Result + UnqualifiedType; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +// August 22, 2001: ported by Jonathan H Lundquist to MSVC +//////////////////////////////////////////////////////////////////////////////// + +#endif // TYPETRAITS_INC_ diff --git a/MSVC/1300/portby.txt b/MSVC/1300/portby.txt new file mode 100644 index 0000000..7f088f3 --- /dev/null +++ b/MSVC/1300/portby.txt @@ -0,0 +1,3 @@ +MSVC7 +Jonathan H. Lundquist +Shannon G. Barber (aka Magmai Kai Holmlor) \ No newline at end of file diff --git a/MSVC/1300/static_check.h b/MSVC/1300/static_check.h new file mode 100644 index 0000000..42662d0 --- /dev/null +++ b/MSVC/1300/static_check.h @@ -0,0 +1,51 @@ +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +//////////////////////////////////////////////////////////////////////////////// + +// Last update: June 20, 2001 + +#ifndef STATIC_CHECK_INC_ +#define STATIC_CHECK_INC_ + +namespace Loki +{ +//////////////////////////////////////////////////////////////////////////////// +// Helper structure for the STATIC_CHECK macro +//////////////////////////////////////////////////////////////////////////////// + + template struct CompileTimeError; + template<> struct CompileTimeError {}; +} + +//////////////////////////////////////////////////////////////////////////////// +// macro STATIC_CHECK +// Invocation: STATIC_CHECK(expr, id) +// where: +// expr is a compile-time integral or pointer expression +// id is a C++ identifier that does not need to be defined +// If expr is zero, id will appear in a compile-time error message. +//////////////////////////////////////////////////////////////////////////////// + +#define STATIC_CHECK(expr, msg) \ + { Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } + + +//////////////////////////////////////////////////////////////////////////////// +// Change log: +// March 20, 2001: add extra parens to STATIC_CHECK - it looked like a fun +// definition +// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! +//////////////////////////////////////////////////////////////////////////////// + +#endif // STATIC_CHECK_INC_