C++ 展平(序列的)序列
我正在使用boost::fusion 假设我有如下内容:C++ 展平(序列的)序列,c++,boost,boost-fusion,C++,Boost,Boost Fusion,我正在使用boost::fusion 假设我有如下内容: make_vector(1, make_vector('b', 3, make_vector(4, 5.5), "six"), 7, 8) 我想产生一个函数f,这样 f(make_vector(1, make_vector('b', 3, make_vector(4, 5.5), "six"), 7, 8)) -> [1, 'b', 3, 4, 5.5, "six", 7, 8] i、 e.序列的扁平版本 我不介意这是原始序列
make_vector(1, make_vector('b', 3, make_vector(4, 5.5), "six"), 7, 8)
我想产生一个函数f,这样
f(make_vector(1, make_vector('b', 3, make_vector(4, 5.5), "six"), 7, 8))
-> [1, 'b', 3, 4, 5.5, "six", 7, 8]
i、 e.序列的扁平版本
我不介意这是原始序列的视图还是实际的向量
如果C++0x可以在GCC4.5.1上编译,我不介意它的解决方案
注:
虽然我不想限制数据元素,但如果有帮助的话,可以随意要求“数据”元素都派生自一个公共基类
i、 e
我想,然后你可以通过使用“is_base_of”来计算出数据元素是什么。这里有一个可能的解决方案,递归使用。基本上,它执行以下操作(在伪Haskell中): 递归地,扁平的头部连接到扁平的尾部 这个解决方案很可能不是最有效的,因为它构造了许多视图,甚至是单个值;更好的方法是在递归调用中将结果序列作为参数传递,并直接在其中添加各个元素,可能使用 下面是代码(免责声明:我写得很快,因此代码中可能会充满bug和/或非惯用的操作方式): 的命名空间结果 { 模板
WOW!谢谢,我试试这个,再仔细看看。这看起来很像我正在浏览的一些boost源代码。我也基于Haskell版本的想法,但如果没有编译错误,我无法获得正确的enable_if。
class DataBase {}
template <class T>
class Data : public DataBase
{
public:
Data(const T& x) : m_x(x)
T m_x;
}
template <class T>
T make_data(const T& x) { return Data<T>(x); }
make_vector(
make_data(1),
make_vector(
make_data('b'),
make_data(3),
make_vector(
make_data(4),
make_data(5.5)
),
make_data("six")
),
make_data(7),
make_data(8)
)
flatten [] = []
flatten x = [x]
flatten (x:xs) = flatten x ++ flatten xs
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 ) );
}