我正在使用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中的等效函数。
答案 0 :(得分:1)
您可以通过实现push_back
MPL运算符来使用自定义类型来实现此目的。
#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");
}
如果您只需要使用MPL序列类型实例化std::tuple
:
#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");
}
答案 1 :(得分:0)
我发现使用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>{}, "");
}