Пару велосипедов для работы с Loki::TypeList
От: VNG Беларусь https://organicmaps.app/
Дата: 18.03.05 17:49
Оценка: 10 (2)
Вот наваял пару велосипедов для работы с 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 >>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.