読者です 読者をやめる 読者になる 読者になる

Boost.Fusion copyアルゴリズムを書いた

C++

提案するかどうかは悩み中ですが、いちおう置いておきます。

#include <string>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/list.hpp>
#include <boost/fusion/include/make_list.hpp>
#include <boost/fusion/include/vector_tie.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/comparison.hpp>
#include <boost/detail/lightweight_test.hpp>

#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/equal_to.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/static_assert.hpp>

template <class IIteratorFirst, class IIteratorLast, class OIteratorFirst>
void copy_impl(IIteratorFirst ifirst, IIteratorLast ilast, OIteratorFirst result, boost::mpl::true_)
{
}

template <class IIteratorFirst, class IIteratorLast, class OIteratorFirst>
void copy_impl(IIteratorFirst ifirst, IIteratorLast ilast, OIteratorFirst result, boost::mpl::false_)
{
    namespace fusion = boost::fusion;

    *result = *ifirst;

    copy_impl(fusion::next(ifirst), ilast, fusion::next(result),
                fusion::result_of::equal_to<
                    typename fusion::result_of::next<IIteratorFirst>::type,
                    IIteratorLast
                >());
}

template <class InputSequence, class OutputSequence>
void copy(const InputSequence& input, OutputSequence& output)
{
    namespace fusion = boost::fusion;

    BOOST_STATIC_ASSERT(fusion::result_of::size<InputSequence>::value ==
                        fusion::result_of::size<OutputSequence>::value);

    copy_impl(fusion::begin(input), fusion::end(input), fusion::begin(output),
                fusion::result_of::equal_to<
                    typename fusion::result_of::begin<InputSequence>::type,
                    typename fusion::result_of::end<InputSequence>::type
                >());
}



struct Data {
    int i;
    char c;
    std::string s;
};

bool operator==(const Data& lhs, const Data& rhs)
{
    return boost::fusion::vector_tie(lhs.i, lhs.c, lhs.s) ==
           boost::fusion::vector_tie(rhs.i, rhs.c, rhs.s);
}


BOOST_FUSION_ADAPT_STRUCT(
    Data,
    (int, i)
    (char, c)
    (std::string, s)
)

int main()
{
    namespace fusion = boost::fusion;

    const fusion::vector<int, char, std::string> v(1, 'a', "Hello");

    {
        fusion::list<int, char, std::string> ls;
        copy(v, ls);

        BOOST_TEST(ls == fusion::make_list(1, 'a', "Hello"));
    }
    {
        Data data;
        copy(v, data);

        Data expected;
        expected.i = 1;
        expected.c = 'a';
        expected.s = "Hello";

        BOOST_TEST(data == expected);
    }

    return boost::report_errors();
}