Получить обычный список MPL из операции push_front - PullRequest
0 голосов
/ 29 мая 2018

Я использую Boost.MPL, у меня есть список времени компиляции (boost::mpl::list).Когда я возвращаю элемент назад, я получаю что-то, что, вероятно, эквивалентно списку, но не является boost::mpl::list.

#include <boost/mpl/list.hpp>
int main(){
    using l = boost::mpl::push_front<boost::mpl::list<int, double, std::string>, char>::type;
}

l, равным boost::mpl::l_item<mpl_::long_<4>, char, boost::mpl::list3<int, double, std::__cxx11::basic_string<char> > >

Как я могупреобразование l в собственное boost::mpl::list<char, int, double, std::string>?

В Boost.Fusion у нас есть boost::fusion:as_list, но я не могу найти эквивалентную функцию в Boost.MPL.

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Я нашел довольно короткую реализацию, используя boost::mpl::fold:

#include<tuple>
#include<boost/mpl/fold.hpp>

///////////////////////////////////////////////////////////
template<class, class> struct tuple_push_back;
template<class... Vs, class T>
struct tuple_push_back<std::tuple<Vs...>, T>{using type=std::tuple<Vs..., T>;};

template<class Set> 
using tuple_of_set_t = typename boost::mpl::fold<
    Set, std::tuple<>, tuple_push_back<boost::mpl::_1, boost::mpl::_2>
>::type;
//////////////////////////////////////////////////////////

#include<boost/mpl/list.hpp>
#include<boost/mpl/push_front.hpp>
#include<string>

int main(){
    using aux_list = boost::mpl::list<double, int, std::string>;
    using a_list = boost::mpl::push_front<aux_list, char>::type;
    using a_tuple = tuple_of_set_t<a_list>;
    static_assert(std::is_same<std::tuple<char, double, int, std::string>, a_tuple>{}, "");
}
0 голосов
/ 18 сентября 2018

Этого можно добиться с помощью пользовательского типа, применив для него оператор MPL push_back.

#include <boost/mpl/list.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <string>
#include <type_traits>
#include <tuple>


struct type_pack_tag;

template <typename... T>
struct type_pack
{
    using tag = type_pack_tag; // MPL tag

    template <typename... U>
    using append = type_pack<T..., U...>;

    template <template <typename...> class F>
    using transfer = F<T...>;
};

namespace boost { namespace mpl {

template <>
struct push_back_impl<type_pack_tag>
{
    template <typename TypePack, typename T> struct apply
    {
        using type = typename TypePack::template append<T>;
    };
};

}}

// Just a shortcut
template <template <typename...> class F, typename T>
using transfer_mpl_seq_to_t =
    typename boost::mpl::copy<
        T, boost::mpl::back_inserter<type_pack<>>
    >::type::template transfer<F>;

int main()
{
    using l = boost::mpl::push_front<boost::mpl::list<int, double, std::string>, char>::type;

    using pack = boost::mpl::copy<l, boost::mpl::back_inserter<type_pack<>>>::type;
    static_assert(std::is_same<pack, type_pack<char, int, double, std::string>>::value, "must be equal");
    static_assert(std::is_same<pack::transfer<boost::mpl::list>, boost::mpl::list<char, int, double, std::string>>::value, "must be equal");

    // Test the shortcut
    static_assert(std::is_same<transfer_mpl_seq_to_t<boost::mpl::list, l>, boost::mpl::list<char, int, double, std::string>>::value, "must be equal");
    static_assert(std::is_same<transfer_mpl_seq_to_t<std::tuple, l>, std::tuple<char, int, double, std::string>>::value, "must be equal");
}

Если вам просто нужно создать экземпляр std::tuple с типами последовательности MPL:

#include <boost/mpl/sequence_tag_fwd.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <string>
#include <type_traits>
#include <tuple>


struct std_tuple_tag;

namespace boost { namespace mpl {

    template <typename... T>
    struct sequence_tag<std::tuple<T...>>
    {
        typedef std_tuple_tag type;
    };

}}


namespace boost { namespace mpl {

template <>
struct push_back_impl<std_tuple_tag>
{
    template <typename Tuple, typename T> struct apply;

    template <typename... T, typename AppendT>
    struct apply<std::tuple<T...>, AppendT>
    {
        using type = std::tuple<T..., AppendT>;
    };
};

}}

int main()
{
    using l = boost::mpl::push_front<boost::mpl::list<int, double, std::string>, char>::type;

    using tpl = boost::mpl::copy<l, boost::mpl::back_inserter<std::tuple<>>>::type;
    static_assert(std::is_same<tpl, std::tuple<char, int, double, std::string>>::value, "must be equal");
}

Или даже проще:

#include <boost/mpl/list.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/back_inserter.hpp>
#include <string>
#include <type_traits>
#include <tuple>


namespace boost { namespace mpl {

template <typename... T, typename AppendT>
struct push_back<std::tuple<T...>, AppendT>
{
    using type = std::tuple<T..., AppendT>;
};

}}

int main()
{
    using l = boost::mpl::push_front<boost::mpl::list<int, double, std::string>, char>::type;

    using tpl = boost::mpl::copy<l, boost::mpl::back_inserter<std::tuple<>>>::type;
    static_assert(std::is_same<tpl, std::tuple<char, int, double, std::string>>::value, "must be equal");
}
...