ボレロ村上 - ENiyGmaA Code

中3女子です。

linearize.hpp

ふと思い立ったので書いてみた。
ネストされたMPLのシーケンスを、
一つのシーケンスに直線化(?)するメタ関数。

  • linearize.hpp
#ifndef SPRIG_TMP_LINEARIZE_HPP
#define SPRIG_TMP_LINEARIZE_HPP

#include <sprig/config/config.hpp>

#ifdef SPRIG_USING_PRAGMA_ONCE
#   pragma once
#endif  // #ifdef SPRIG_USING_PRAGMA_ONCE

#include <boost/mpl/identity.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/lambda.hpp>

namespace sprig {
    namespace tmp {
        //
        // linearize
        //
        template<
            typename Sequence,
            typename Inserter = boost::mpl::back_inserter<boost::mpl::vector0<> >
        >
        struct linearize
            : public boost::mpl::fold<
                Sequence,
                typename Inserter::state,
                boost::mpl::eval_if<
                    boost::mpl::is_sequence<boost::mpl::_2>,
                    linearize<
                        boost::mpl::_2,
                        boost::mpl::identity<
                            boost::mpl::inserter<
                                boost::mpl::_1,
                                typename Inserter::operation
                            >
                        >
                    >,
                    typename Inserter::operation::template apply<
                        boost::mpl::_1,
                        boost::mpl::_2
                    >
                >
            >
        {};
    }   // namespace tmp
}   // namespace sprig

#endif  // #ifndef SPRIG_TMP_LINEARIZE_HPP


テスト。

  • test-linearize.cpp
#include <boost/mpl/vector.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/assert.hpp>
#include <sprig/tmp/linearize.hpp>

typedef boost::mpl::vector<
    short,
    int,
    long,
    long long,
    __int8,
    __int16,
    __int32,
    __int64,
    unsigned short,
    unsigned,
    unsigned long,
    unsigned long long,
    unsigned __int8,
    unsigned __int16,
    unsigned __int32,
    unsigned __int64,
    float,
    double,
    long double,
    void
> sequence_t;

typedef boost::mpl::vector<
    boost::mpl::vector<
        short,
        int,
        long,
        long long
    >,
    __int8,
    __int16,
    __int32,
    __int64,
    boost::mpl::vector<
        boost::mpl::vector<
            unsigned short,
            unsigned,
            unsigned long,
            unsigned long long
        >,
        unsigned __int8,
        unsigned __int16,
        unsigned __int32,
        unsigned __int64
    >,
    boost::mpl::vector<
        boost::mpl::vector<
            float,
            double,
            long double
        >
    >,
    void
> nested_sequence_t;

typedef sprig::tmp::linearize<nested_sequence_t>::type linearized_t;

BOOST_MPL_ASSERT(( boost::mpl::equal<linearized_t, sequence_t> ));


MPLライクなアルゴリズムを書いたことは大してないので、
効率的なコードはたぶん書けていない。


これとは逆に、MPLシーケンスの要素数の制限を何とかするために
シーケンスを多次元のシーケンスに変換&それを一つのシーケンスとして扱うViewを生成
みたいな処理のほうが実用では必要になるかも。