不同大小的数组数组

5

我有一些代码可以生成不同大小但相同类型的tr1::array集合,例如:

array<int, 2>
array<int, 4>
array<int, 6>

这些数组的数量和大小在编译时给出,所以我知道将有多少个数组以及每个数组的大小(但它们可能不同)。
问题:我想把它们放在一个集合中(使用array<>会很好),但所有成员的类型必须相等,而这并不是实际情况。
我考虑使用boost::variant,但如何指定具有编译时确定的类型列表的变体(我正在考虑大量使用预处理器...)?使用boost::any呢?其他方法呢?(野指针?)
谢谢 ~Aki
更正:在这种情况下不能使用预处理器。

std::vector 可能是最容易的选择。只要不改变大小就可以了。:) 诚然,它并不完全相同,但很干净。 - GManNickG
是的,我已经有了一个实现,使用的是 std::vector 而不是 tr1::array,但是使用动态尺寸是没有意义的,因为它们可以在编译时计算,所以我正在寻找一个静态的解决方案。 - AkiRoss
你可能会喜欢这些容器之一:http://www.boost.org/doc/libs/1_43_0/libs/fusion/doc/html/fusion/container.html。另外,如果你想回复某人,请使用@,例如@aaa。 - Anycorn
就像@aaa所说的那样,您需要使用fusion。我实际上有一个类似的问题,可以生成不同类型的数组,在这里:https://dev59.com/kEvSa4cB1Zd3GeqPdU97。 - GManNickG
3个回答

3
我会使用Boost的MPL和Fusion库。有两种方法可以得到类型列表:生成它们或显式定义它们。前者更灵活,但由于我们不知道您如何获得所需值,很难说哪种方法适合您。
无论如何,如果要生成类型列表:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <array>
#include <iostream>

namespace bmpl = boost::mpl;

// turns an index into an array
template <typename T>
struct make_array
{
    // or whatever scheme you have
    static const std::size_t size = T::value * 2;

    // define generated type
    typedef std::array<int, size> type;
};

// list of values to convert
typedef bmpl::range_c<size_t, 1, 10> array_range;

// transform that list into arrays, into a vector
typedef bmpl::transform<array_range, make_array<bmpl::_1>,
                            bmpl::back_inserter<bmpl::vector<>>
                                >::type array_collection;

或者明确地说明:

#include <boost/mpl/vector.hpp>
#include <array>
#include <iostream>

namespace bmpl = boost::mpl;

// list all array types
typedef bmpl::vector<
            std::array<int, 2>,
            std::array<int, 4>,
            std::array<int, 6>,
            std::array<int, 8>,
            std::array<int, 10>,
            std::array<int, 12>,
            std::array<int, 14>,
            std::array<int, 16>,
            std::array<int, 18>
                > array_collection;

无论哪种方式,您都可以像这样使用它:
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/for_each.hpp>
#include <typeinfo>

// fusion "fuses" the bridge between MPL and runtime
namespace bf = boost::fusion;

struct print_type
{
    template <typename T>
    void operator()(const T&) const
    {
        std::cout << typeid(T).name() << "\n";
    }
};

struct print_values
{
    template <typename T>
    void operator()(const T& pArray) const
    {
        std::cout << "Printing array with size "
                    << pArray.size() << ":\n";
        std::for_each(pArray.begin(), pArray.end(),
                [](int pX)
                {
                    std::cout << pX <<  " ";
                });
        std::cout << std::endl;
    }
};

int main(void)
{
    // print all the types you have
    bmpl::for_each<array_collection>(print_type());
    std::cout.flush();

    // make a usable type out of the typelist
    typedef bf::result_of::as_vector<array_collection>::type array_fusion;
    array_fusion arrays; // now have an array of different arrays,
                         // compile-time generated but run-time usable

    // access like this:
    bf::at_c<0>(arrays)[1] = 5; 
    bf::at_c<1>(arrays)[2] = 7; 
    bf::at_c<2>(arrays)[0] = 135; 

    // for_each:
    bf::for_each(arrays, print_values());
}

MPL似乎是解决方案 :) 谢谢。 - AkiRoss
我总是很高兴看到关于使用一些我认为是“高级”(或者可能只是“新的”)boost库,比如mpl/fusion/proto/phoenix的帖子。有时候我希望能有更多的帖子介绍这些库的优秀用例(甚至有一些问题也没有太多答案)。但是感谢你的示例! - sascha

0
唯一的方法是将不同类型的类放入STL容器中,就是如果容器包含指向某个基本类型的指针(引用不起作用,因为它们不能默认构造),而您想要收集的对象都继承自该类型。请注意,从基类派生的类型的容器(或任何模板类)不会从基本类型的容器中继承。您可以使用void*,但需要进行许多丑陋和危险的转换,并且必须记住自己释放内存。为什么不编写一个固定大小的数组类,允许您在构造函数中设置大小?如果您将其编写为araray的包装器,则不应该太费力。如果您想使用基于智能指针的某些解决方案,请不要尝试使用auto_ptr,因为复制语义对于STL容器来说是错误的-请使用类似于boost shared_ptr的东西。

0

你没有说清楚为什么要使用不同大小的静态数组集合,这很奇怪。为什么不使用动态大小的数组集合呢?

你有以下选择:

  • 使用std::vector代替std::tr1::array。

  • 在你的集合中存储指向数组和数组大小的指针。这可能看起来像:std::vector<std::pair<int *, size_t> >。只需确保数组的生命周期至少与向量的生命周期一样长!

  • 我认为boost::variant也可以工作,但在实践中使用起来会相当麻烦。

boost::variant<array<int, 2>, array<int, 4>, array<int, 6>, ... >


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接