Вот наваял пару велосипедов для работы с Loki::TypeList.
Активно использую в своих проектахю Может кому понадобится.
// ВНГ
// Пару велосипедов для улучшения работы со списками типов и кортежами в библиотеке Loki.
#pragma once
#include "Loki\TypeList.h"
#include "Loki\HierarchyGenerators.h"
#include "Loki\TypeManip.h"
#include "Loki\NullType.h"
/// Макрос для определения функций итерирования по списку типов
#define FOR_EACH_LOKI_TYPELIST(implFunctionName, realFunctionName) \
template <class TList> inline void implFunctionName() \
{ \
realFunctionName<typename TList::Head>(); \
implFunctionName<typename TList::Tail>(); \
} \
template <> inline void implFunctionName<Loki::NullType>() { }
namespace Loki_add
{
#pragma warning (push)
#pragma warning (disable : 4503)
/// Структуры для утобного селектирования
struct Yes { enum { value = 1 }; };
struct No { enum { value = 0 }; };
namespace TL
{
//////////////////////////////////////////////////////////////////////////////////////////////
/// Поиск типа TFindType в списке типов TList по правилу TRule.
/// Если типа не находит, то возвращается NullType.
template <class TList, template<class, class> class TRule, class TFindType> struct FindIf;
template <template<class, class> class TRule, class TFindType>
struct FindIf<Loki::NullType, TRule, TFindType>
{
typedef Loki::NullType Result;
};
template <class Head, class Tail, template<class, class> class TRule, class TFindType>
struct FindIf<Loki::Typelist<Head, Tail>, TRule, TFindType>
{
typedef typename Loki::Select< TRule<Head, TFindType>::value,
Head,
typename FindIf<Tail, TRule, TFindType>::Result
>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////////////////////
namespace impl_remove_if
{
template <class TList, template<class> class TRule, class TNewList> struct Make;
template <template<class> class TRule, class TNewList>
struct Make<Loki::NullType, TRule, TNewList>
{
typedef TNewList Result;
};
template <class Head, class Tail, template<class> class TRule, class TNewList>
struct Make<Loki::Typelist<Head, Tail>, TRule, TNewList>
{
typedef typename Make < Tail,
TRule,
typename Loki::Select < TRule<Head>::value,
TNewList,
typename Loki::TL::Append < TNewList,
Head
>::Result
>::Result
>::Result Result;
};
};
//////////////////////////////////////////////////////////////////////////////////////////////
/// Удаление типов из списка типов TList по правилу TRule.
template <class TList, template<class> class TRule> struct RemoveIf
{
typedef typename impl_remove_if::Make<TList, TRule, Loki::NullType>::Result Result;
};
//////////////////////////////////////////////////////////////////////////////////////////////
namespace impl_transform
{
template <class TList, template<class> class TRule, class TNewList> struct Make;
template <template<class> class TRule, class TNewList>
struct Make<Loki::NullType, TRule, TNewList>
{
typedef TNewList Result;
};
template <class Head, class Tail, template<class> class TRule, class TNewList>
struct Make<Loki::Typelist<Head, Tail>, TRule, TNewList>
{
typedef typename Make < Tail,
TRule,
typename Loki::TL::Append < TNewList,
typename TRule<Head>::Result
>::Result
>::Result Result;
};
};
//////////////////////////////////////////////////////////////////////////////////////////////
/// Формирование нового списка типов по исходному с заданным преобразованием
template <class TList, template<class> class TRule> struct Transform
{
typedef typename impl_transform::Make<TList, TRule, Loki::NullType>::Result Result;
};
namespace impl_sort_list
{
template <class TList, template <class, class> class TRule> struct PushBetterToTop;
template <class Head, template <class, class> class TRule>
struct PushBetterToTop<Loki::Typelist<Head, Loki::NullType>, TRule>
{
typedef Loki::Typelist<Head, Loki::NullType> Result;
};
template <class Head, class Tail, template <class, class> class TRule>
struct PushBetterToTop<Loki::Typelist<Head, Tail>, TRule>
{
private:
// находим лучший элемент по отношению к Head
typedef typename FindIf<Tail, TRule, Head>::Result the_best_element;
// заменяем лучший элемент в Tail элементом Head
typedef typename Loki::Select< Loki::IsSameType<the_best_element, Loki::NullType>::value,
Tail,
typename Loki::TL::Replace<Tail, the_best_element, Head>::Result
>::Result tail_with_replaced_best;
// рекурсивный переход
typedef typename PushBetterToTop<tail_with_replaced_best, TRule>::Result sorted_tail;
public:
// список на выход, где Head - лучший элемент
typedef typename Loki::Select< Loki::IsSameType<the_best_element, Loki::NullType>::value,
Loki::Typelist<Head, sorted_tail>,
Loki::Typelist<the_best_element, sorted_tail>
>::Result Result;
};
// Применяем N раз выдвижение лучшего элемента наверх
template <int N, class TList, template <class, class> class TRule> struct ApplyNTymes
{
typedef typename ApplyNTymes<N-1, typename PushBetterToTop<TList, TRule>::Result, TRule>::Result Result;
};
template <class TList, template <class, class> class TRule> struct ApplyNTymes<0, TList, TRule>
{
typedef TList Result;
};
};
//////////////////////////////////////////////////////////////////////////////////////////////
/// Сортировка списка типов.
/// В итоге в Head будет элемент для которого TRule<Head, T>::value = 1, для любого T.
/// ... и так далее по прохождению списка.
template <class TList, template <class, class> class TRule> struct Sort
{
typedef typename impl_sort_list::ApplyNTymes<Loki::TL::Length<TList>::value-1, TList, TRule>::Result Result;
};
};
#pragma warning (pop)
};
namespace Loki_add
{
#pragma warning (push)
#pragma warning (disable : 4503)
//////////////////////////////////////////////////////////////////////////////////////////////
/// Кортеж с функциями доступа к элементам по типу параметра.
/// Сравнение производится по стратегии TRule - по умолчанию проверяется равенство типов.
template <class TList> class CExtendedTuple
{
Loki::Tuple<TList> m_data;
template <class Head, class Tail, class Unit, class TWhatToDo>
inline static void ForEachImpl(Loki::GenScatterHierarchy<Loki::Typelist<Head, Tail>, Unit> & theTuple, TWhatToDo toDo)
{
Head & head = theTuple;
toDo(head);
Loki::GenScatterHierarchy<Tail, Unit> & tail = theTuple;
ForEachImpl(tail, toDo);
}
template <class Unit, class TWhatToDo>
inline static void ForEachImpl(Loki::GenScatterHierarchy<Loki::NullType, Unit> &, TWhatToDo)
{
}
public:
/// Проверка, находится ли тип TFindType в кортеже - value и
/// получение типа элемента в кортеже по критерию - Result.
template <class TFindType, template <class, class> class TRule = Loki::IsSameType> struct IsExist
{
typedef typename Loki_add::TL::FindIf<TList, TRule, TFindType>::Result Result;
enum { value = !Loki::IsSameType<Result, Loki::NullType>::value };
};
/// Итерирование по элементам кортежа
template <class TWhatToDo> void ForEach(TWhatToDo toDo) { ForEachImpl(m_data, toDo); }
//////////////////////////////////////////////////////////////////////////////////////////////
/// Функции доступа к элементам кортежа.
/// Функции доступа с выявлением подходящего типа по правилу TRule.
template<class TSrcType, template <class, class> class TRule>
typename Loki_add::TL::FindIf<TList, TRule, TSrcType>::Result& get_ex()
{
typedef typename Loki_add::TL::FindIf<TList, TRule, TSrcType>::Result result_type;
return Loki::Field<result_type>(m_data);
}
template<class TSrcType, template <class, class> class TRule>
typename Loki_add::TL::FindIf<TList, TRule, TSrcType>::Result const & get_ex() const
{
typedef typename Loki_add::TL::FindIf<TList, TRule, TSrcType>::Result result_type;
return Loki::Field<result_type>(m_data);
}
template<class TSrcType, template <class, class> class TRule, class TData>
void set_ex(TData const & data) { get_ex<TSrcType, TRule>() = data; }
/// Обычные функции доступа с выявлением типа на предмет полного соответсвия.
template<class TSrcType>
typename Loki_add::TL::FindIf<TList, Loki::IsSameType, TSrcType>::Result& get()
{
typedef typename Loki_add::TL::FindIf<TList, Loki::IsSameType, TSrcType>::Result result_type;
return Loki::Field<result_type>(m_data);
}
template<class TSrcType>
typename Loki_add::TL::FindIf<TList, Loki::IsSameType, TSrcType>::Result const & get() const
{
typedef typename Loki_add::TL::FindIf<TList, Loki::IsSameType, TSrcType>::Result result_type;
return Loki::Field<result_type>(m_data);
}
template<class TSrcType, class TData>
void set(TData const & data) { get<TSrcType>() = data; }
};
#pragma warning (pop)
};
... << RSDN@Home 1.1.4 beta 2 >>