📄 variant.h
字号:
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001, 2002 by Andrei Alexandrescu
// 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 makes no representations about the suitability of this software
// for any purpose. It is provided "as is"
// without express or implied warranty.
////////////////////////////////////////////////////////////////////////////////
#ifndef VARIANT_INC_
#define VARIANT_INC_
#include <cstddef>
#include <memory>
#include <typeinfo>
#include "Visitor.h"
#include "Typelist.h"
#include "static_check.h"
//
// At the moment there is no namespace for Variant
//
#ifdef _MSC_VER
# include "VC_Alignment.h"
#endif
////////////////////////////////////////////////////////////////////////////////
// class template ConfigurableUnion
// Builds a union that contains each type in a typelist
// Usage: ConfigurableUnion<TList> is the very type
////////////////////////////////////////////////////////////////////////////////
template <class U> union ConfigurableUnion;
template <> union ConfigurableUnion< ::Loki::NullType >
{
};
template <class TList>
union ConfigurableUnion
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
public:
Head head_;
ConfigurableUnion<Tail> tail_;
};
////////////////////////////////////////////////////////////////////////////////
// class template MaxSize
// Computes the maximum sizeof for all types in a typelist
// Usage: MaxSize<TList>::result
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct MaxSize;
template <>
struct MaxSize< ::Loki::NullType >
{
enum { result = 0 };
};
template <class TList>
struct MaxSize
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
enum { headResult = sizeof(Head) };
enum { tailResult = MaxSize<Tail>::result };
public:
enum { result = headResult > tailResult ?
headResult : tailResult };
};
////////////////////////////////////////////////////////////////////////////////
// class AlignedPODBase
// Defines a host of protected types used by AlignedPOD (defined later)
// Could be just part of AlignedPOD itself, but making it separate ought to
// reduce compile times
////////////////////////////////////////////////////////////////////////////////
class AlignedPODBase
{
protected:
template <class TList, std::size_t size>
struct ComputeAlignBound
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
template<class TList1>
struct In
{
private:
typedef typename TList1::Head Head1;
typedef typename TList1::Tail Tail1;
typedef typename ComputeAlignBound<Tail1, size>::Result TailResult;
public:
typedef typename ::Loki::Select
<
sizeof(Head1) <= size,
::Loki::Typelist<Head1, TailResult>,
TailResult
>
::Result Result;
};
template<>
struct In< ::Loki::NullType >
{
typedef ::Loki::NullType Result;
};
public:
typedef typename In<TList>::Result Result;
};
template <typename U> struct Structify
{ U dummy_; };
class Unknown;
// VC7: fatal error C1067: compiler limit :
// debug information module size exceeded
// Therfore I decreased the list to 26 without
// changing the rage of detectable alignment
typedef TYPELIST_26(
char,
wchar_t,
short int,
int,
long int,
float,
double,
long double,
char*,
void*,
Unknown (*)(Unknown),
Unknown* Unknown::*,
Unknown (Unknown::*)(Unknown),
Structify<char>,
Structify<wchar_t>,
Structify<short int>,
Structify<int>,
Structify<long int>,
Structify<float>,
Structify<double>,
Structify<long double>,
Structify<char*>,
Structify<void*>,
Structify<Unknown (*)(Unknown)>,
Structify<Unknown* Unknown::*>,
Structify<Unknown (Unknown::*)(Unknown)>
)
TypesOfAllAlignments;
};
////////////////////////////////////////////////////////////////////////////////
// class template AlignedPOD
// Computes the alignment of all types in a typelist
// Usage: ConfigurableUnion<TList> is the very type
////////////////////////////////////////////////////////////////////////////////
template <typename TList>
class AlignedPOD : private AlignedPODBase
{
enum { maxSize = MaxSize<TList>::result };
typedef typename ComputeAlignBound
<
TypesOfAllAlignments,
maxSize
>
::Result AlignTypes;
public:
typedef ConfigurableUnion<AlignTypes> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template MakeConst
// Given a typelist TList, returns a typelist that contains the types in TList
// adding a const qualifier to each.
// Usage: MakeConst<TList>::Result
////////////////////////////////////////////////////////////////////////////////
template <class TList> struct MakeConst;
template <> struct MakeConst< ::Loki::NullType >
{
typedef ::Loki::NullType Result; // terminator is not const
};
template <class TList>
struct MakeConst
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Head;
typedef typename TList::Tail Tail;
private:
typedef typename MakeConst<Tail>::Result NewTail;
public:
typedef ::Loki::Typelist<const Head, NewTail> Result;
};
////////////////////////////////////////////////////////////////////////////////
// class template Converter
// Supports the Variant-to-Variant conversion constructor
// Guaranteed to issue an internal compiler error on:
// 1. Metrowerks CodeWarrior 7.0 (internal compiler error: File:
// 'CTemplateTools.c' Line: 1477
// Variant.h line 244 UnitBase > VisitorBase;)
// 2. Microsoft Visual C++ 7.1 alpha release (Assertion failed:
// ( name - nameBuf ) < LIMIT_ID_LENGTH,
// file f:\vs70builds\2108\vc\Compiler\CxxFE\sl\P1\C\outdname.c,
// line 4583)
// 3. GNU gcc 2.95.3-6 (Internal compiler error 980422)
////////////////////////////////////////////////////////////////////////////////
template <class VariantFrom, class VariantTo>
struct Converter
{
//private: VC7 complains
struct UnitBase : public VariantFrom::ConstStrictVisitor
{
protected:
VariantTo* storageForDestination;
};
template <class Type, class Base>
struct Unit : public Base
{
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{
new(this->storageForDestination) VariantTo(obj);
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
typedef typename VariantTo::Types TList;
enum { dispatch = TL::IndexOf<TList, Type>::value > -1 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
private:
typedef ::Loki::GenLinearHierarchy
<
typename VariantFrom::Types,
Unit,
UnitBase
>
VisitorBase;
public:
struct Visitor : public VisitorBase
{
explicit Visitor(VariantTo& dest)
{
// Initialize the pointer to destination
this->storageForDestination = &dest;
}
};
};
////////////////////////////////////////////////////////////////////////////////
// class template ConverterTo
// Supports Variant-to-T conversion
////////////////////////////////////////////////////////////////////////////////
#if 0
template <class VariantFrom, class T>
struct ConverterTo
{
private:
struct DestHolder
: VariantFrom::ConstStrictVisitor
{
protected:
DestHolder() {}
DestHolder(const T& dest) : destination_(dest) {}
T destination_;
};
template <class TList>
struct VisitorBase
: VisitorBase<typename TList::Tail>
{
private:
ASSERT_TYPELIST(TList);
typedef typename TList::Head Type;
typedef typename TList::Tail Tail;
protected:
VisitorBase<TList>() {}
VisitorBase<TList>(const T& dest)
: VisitorBase<Tail>(dest) {}
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{ //
// T temp(obj)
// swap(destination_, temp) or destination_ = temp
//
this->destination_ = obj;
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
enum { dispatch = Conversion<Type, T>::exists != 0 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
template <>
struct VisitorBase< ::Loki::NullType >
: DestHolder
{
protected:
VisitorBase< ::Loki::NullType >() {}
VisitorBase< ::Loki::NullType >(const T& dest)
: DestHolder(dest) {}
};
typedef VisitorBase
<
typename VariantFrom::Types
>
VisitorBaseType;
public:
struct Visitor : public VisitorBaseType
{
Visitor() {}
explicit Visitor(const T& dest)
: VisitorBaseType(dest) {}
const T &GetDestination() const
{ return this->destination_; }
};
};
#else
template <class VariantFrom, class T>
struct ConverterTo
{
//private:
struct UnitBase : public VariantFrom::ConstStrictVisitor
{
protected:
T destination_;
};
template <class Type, class Base>
struct Unit : public Base
{
private:
void DoVisit(const Type& obj, ::Loki::Int2Type<true>)
{
this->destination_ = obj;
}
void DoVisit(const Type&, ::Loki::Int2Type<false>)
{
throw std::runtime_error("Cannot convert");
}
virtual void Visit(const Type& obj)
{
using namespace Loki;
enum { dispatch = Conversion<Type, T>::exists != 0 };
this->DoVisit(obj, Int2Type<dispatch>());
}
};
typedef ::Loki::GenLinearHierarchy<
typename VariantFrom::Types,
Unit,
UnitBase > VisitorBase;
public:
struct Visitor : public VisitorBase
{
const T &GetDestination() const
{ return this->destination_; }
};
};
#endif
namespace Private
{
template<typename T>
struct RawDataKeeper
{
private:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -