我有以下示例:
#include <iostream>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/list.hpp>
struct one {};
struct two {};
struct three {};
struct four {};
struct five { five() = delete; };
template <typename T>
void print()
{
std::cout << "hello " << typeid(T).name() << std::endl;
}
struct type_printer
{
template <typename T>
void operator()(T)
{
print<T>();
}
};
int main()
{
typedef boost::mpl::list<
one,
two,
three,
four,
five
>::type type_list;
boost::mpl::for_each<type_list>(type_printer());
}
如果我不在列表中包含第五个对象,哪个工作绝对正常,但是一旦我这样做,我会收到以下错误:
In file included from /usr/local/include/boost_1_56_0/boost/mpl/for_each.hpp:29:0,
from mpldef.cpp:3:
/usr/local/include/boost_1_56_0/boost/utility/value_init.hpp: In constructor ‘boost::initialized<T>::wrapper::wrapper() [with T = five]’:
/usr/local/include/boost_1_56_0/boost/utility/value_init.hpp:109:7: instantiated from ‘boost::initialized<T>::initialized() [with T = five]’
/usr/local/include/boost_1_56_0/boost/utility/value_init.hpp:205:12: instantiated from ‘boost::value_initialized<T>::value_initialized() [with T = five]’
/usr/local/include/boost_1_56_0/boost/mpl/for_each.hpp:81:9: recursively instantiated from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::l_iter<boost::mpl::list4<two, three, four, five> >, LastIterator = boost::mpl::l_iter<boost::mpl::l_end>, TransformFunc = boost::mpl::identity<mpl_::na>, F = type_printer]’
/usr/local/include/boost_1_56_0/boost/mpl/for_each.hpp:81:9: instantiated from ‘static void boost::mpl::aux::for_each_impl<false>::execute(Iterator*, LastIterator*, TransformFunc*, F) [with Iterator = boost::mpl::l_iter<boost::mpl::list5<one, two, three, four, five> >, LastIterator = boost::mpl::l_iter<boost::mpl::l_end>, TransformFunc = boost::mpl::identity<mpl_::na>, F = type_printer]’
/usr/local/include/boost_1_56_0/boost/mpl/for_each.hpp:104:5: instantiated from ‘void boost::mpl::for_each(F, Sequence*, TransformOp*) [with Sequence = boost::mpl::list5<one, two, three, four, five>, TransformOp = boost::mpl::identity<mpl_::na>, F = type_printer]’
/usr/local/include/boost_1_56_0/boost/mpl/for_each.hpp:118:3: instantiated from ‘void boost::mpl::for_each(F, Sequence*) [with Sequence = boost::mpl::list5<one, two, three, four, five>, F = type_printer]’
mpldef.cpp:37:48: instantiated from here
/usr/local/include/boost_1_56_0/boost/utility/value_init.hpp:77:12: error: use of deleted function ‘five::five()’
mpldef.cpp:10:15: error: declared here
有没有办法做到这一点?我尝试从T
调用运算符中删除type_printer
,所以它看起来像这样:void operator()()
我仍然遇到同样的错误。
答案 0 :(得分:3)
我通过添加类型包装器结构来解决这个问题,例如在Boost.Hana中看到的the one。我将此添加到this comment中提到的好主意,该主意提到使用boost::mpl::transform
自动将此包装类型添加到列表中的每个项目。
以下详述我的解决方案:
template <typename T>
struct type_
{
using type = T;
};
template <typename T>
struct add_type_wrapper
{
using type = type_<T>;
};
使用这两种新类型,我将type_printer
仿函数更改为:
struct type_printer
{
template <typename T>
void operator()(T)
{
using type_t = typename T::type;
print<type_t>();
}
};
现在主要的boost::mpl::for_each
电话看起来像这样:
using boost::mpl::_1;
using wrapped_list = boost::mpl::transform<type_list, add_type_wrapper<_1>>::type;
boost::mpl::for_each<wrapped_list>(type_printer());
感谢您的帮助,我认为这是一个非常好的优雅解决方案。
答案 1 :(得分:2)
您还可以为类型列表中的项添加一个间接级别,如下所示:
template <typename T>
struct type_ref
{
typedef T type;
}
struct type_printer
{
template <typename T>
void operator()(T)
{
print<T>();
}
template <typename T>
void operator()(type_ref<T>)
{
print<T>();
}
};
int main()
{
typedef boost::mpl::list<
one,
two,
three,
four,
type_ref<five>
>::type type_list;
boost::mpl::for_each<type_list>(type_printer());
}
答案 2 :(得分:0)
你可以自己做类似的事情:
namespace detail {
template <typename Tuple>
structure my_for_each_t;
template <typename... Ts>
structure my_for_each_t<boost::mpl::list<Ts...>>
{
template <typename F>
void operator()(F f) const
{
initializer_list<int>{(static_cast<void>(f<Ts>()), 0)...};
}
};
}
template <typename Tuple, typename F>
void my_for_each(F f)
{
detail::my_for_each_t<Tuple>()(f);
}
或转换您的列表以添加指向该类型的指针,并更改您的type_printer
:
struct type_printer
{
template <typename T>
void operator()(T*) // pointer added.
{
print<T>();
}
};