view src/higherorder.cc @ 14:ab9ed41eb455

higherorder: a few exercises
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 27 Mar 2020 15:09:49 +0100
parents a5357921e566
children
line wrap: on
line source

#include <iostream>
#include <boost/static_assert.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/equal.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/multiplies.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector_c.hpp>

namespace mpl = boost::mpl;

template<typename A, typename B>
struct equal {
    typedef mpl::bool_<false> type;
};
template<typename A>
struct equal<A, A> {
    typedef mpl::bool_<true> type;
};

template<int N>
struct arg {
    template<typename A, typename ... As>
    struct apply : arg<N-1>::template apply<As...> {
    };
};

template<>
struct arg<1> {
    template<typename A, typename ... As>
    struct apply {
        typedef A type;
    };
};

struct plus10 {
    template<typename X>
    struct apply {
        typedef typename mpl::int_<10 + X::value>::type type;
    };
};

template<typename F, typename X>
struct apply : public F::template apply<X> {};

template<typename F, typename X>
struct apply_twice : public F::template apply<typename F::template apply<X>::type> {};

int exercises(void) {
    // 3-1
    {
        typedef mpl::vector_c<int, 1, 2, 3> src;
        typedef mpl::transform<src, mpl::plus<mpl::int_<1>, mpl::_>>::type dst;
        BOOST_STATIC_ASSERT(3 == mpl::at<dst, mpl::int_<1>>::type::value);
    }
    // 3-3
    {
        typedef mpl::lambda<apply_twice<mpl::lambda<std::add_pointer<mpl::_>>::type, mpl::_>, mpl::_>::type ptrtwice;
        typedef mpl::lambda<apply_twice<ptrtwice, mpl::_>>::type ptrquad;
        BOOST_STATIC_ASSERT(equal<double****, mpl::apply<ptrquad, double>::type>::type::value);
        std::cout << typeid(mpl::apply<ptrquad, double>::type).name();
    }
    return 0;
}

int arg_test(void) {
    BOOST_STATIC_ASSERT(3 == arg<2>::template apply<mpl::int_<1>, mpl::int_<3>, mpl::int_<2>>::type::value);
    std::cout << arg<2>::template apply<mpl::int_<1>, mpl::int_<3>, mpl::int_<2>>::type::value;
    return 0;
}

int test(void) {
    typedef mpl::int_<3> three;
    // lambda<> takes a placeholder expression and returns a metafunction class.
    typedef mpl::lambda<mpl::plus<mpl::int_<11>, mpl::_1>>::type plus11;
    typedef mpl::lambda<plus10>::type plus10_2;

    typedef mpl::vector_c<int, 1, 2, 3> seq1;
    typedef mpl::transform<seq1, plus10>::type seq2;
    std::cout << apply_twice<plus11, three>::type::value << " " << mpl::at<seq2, mpl::int_<2>>::type::value << std::endl;
    return 0;
}

int main(void) {
    exercises();
    return 0;
}