Вот одно из возможных решений, которое использует join
рекурсивно. По сути, он делает следующее (в псевдо-Хаскеле):
flatten [] = []
flatten x = [x]
flatten (x:xs) = flatten x ++ flatten xs
Рекурсивно уплощенная голова соединяется со сплющенным хвостом.
Это решение, скорее всего, не самое эффективное, поскольку оно строит множество представлений даже для отдельных значений; лучшим подходом может быть передача результирующей последовательности в качестве параметра в рекурсивных вызовах и непосредственное добавление в нее отдельных элементов, возможно, с использованием fold
.
Вот код (заявление об отказе: я написал это довольно быстро, чтобы код мог быть заполнен ошибками и / или неидиоматическими способами выполнения действий):
namespace result_of
{
template < typename Begin, typename End, class Enable = void >
struct flatten_impl
{
typedef boost::fusion::single_view< typename
boost::fusion::result_of::value_of< Begin >::type
> flattenedHeadSequence;
typedef typename
flatten_impl< typename
boost::fusion::result_of::next< Begin >::type,
End
>::type flattenedTailSequence;
typedef typename boost::fusion::result_of::join< const flattenedHeadSequence, const flattenedTailSequence >::type type;
};
template < typename Begin, typename End >
struct flatten_impl<
Begin,
End, typename
boost::enable_if<
boost::fusion::traits::is_sequence< typename
boost::fusion::result_of::value_of< Begin >::type
>
>::type
>
{
typedef typename boost::fusion::result_of::value_of< Begin >::type headSequence;
typedef typename
flatten_impl< typename
boost::fusion::result_of::begin< headSequence >::type, typename
boost::fusion::result_of::end< headSequence >::type
>::type flattenedHeadSequence;
typedef typename
flatten_impl< typename
boost::fusion::result_of::next< Begin >::type,
End
>::type flattenedTailSequence;
typedef typename boost::fusion::result_of::join< const flattenedHeadSequence, const flattenedTailSequence >::type type;
};
template < typename End, typename Enable >
struct flatten_impl< End, End, Enable >
{
typedef boost::fusion::vector< > type;
};
template < typename Sequence >
struct flatten
{
typedef typename
flatten_impl< typename
boost::fusion::result_of::begin< Sequence >::type, typename
boost::fusion::result_of::end< Sequence >::type
>::type type;
};
}
template < typename Begin, typename End >
typename result_of::flatten_impl< Begin, End >::type
flatten_impl(
const Begin & begin,
const End & end, typename
boost::disable_if<
boost::fusion::traits::is_sequence< typename
boost::fusion::result_of::value_of< Begin >::type
>
>::type * dummy = 0 )
{
typedef result_of::flatten_impl< Begin, End > traits;
typedef typename traits::flattenedHeadSequence headSequence;
typedef typename traits::flattenedTailSequence tailSequence;
return boost::fusion::join(
headSequence( boost::fusion::deref( begin ) ),
flatten_impl( boost::fusion::next( begin ), end ) );
}
template < typename Begin, typename End >
typename result_of::flatten_impl< Begin, End >::type
flatten_impl(
const Begin & begin,
const End & end, typename
boost::enable_if<
boost::fusion::traits::is_sequence< typename
boost::fusion::result_of::value_of< Begin >::type
>
>::type * dummy = 0 )
{
typedef result_of::flatten_impl< Begin, End > traits;
typedef typename traits::flattenedHeadSequence headSequence;
typedef typename traits::flattenedTailSequence tailSequence;
typedef typename boost::fusion::result_of::value_of< Begin >::type headType;
const headType & head = boost::fusion::deref( begin );
return boost::fusion::join(
flatten_impl( boost::fusion::begin( head ), boost::fusion::end( head ) ),
flatten_impl( boost::fusion::next( begin ), end ) );
}
template < typename End >
typename result_of::flatten_impl< End, End >::type
flatten_impl( const End &, const End &)
{
return boost::fusion::make_vector( );
}
template < typename Sequence >
typename result_of::flatten< Sequence >::type
flatten( const Sequence & seq )
{
return flatten_impl( boost::fusion::begin( seq ), boost::fusion::end( seq ) );
}