【问题标题】:array of arrays of different size不同大小的数组数组
【发布时间】:2010-07-28 00:04:30
【问题描述】:

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

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

这些数组的数量和它们的大小在编译时给出,所以我确切地知道它们中有多少以及每个有多大(但它们可能不同)。

问题:我想将它们放在一个集合中(使用数组 会很棒),但是所有成员的类型必须相同,但事实并非如此。

我考虑过使用 boost::variant,但是如何指定具有编译时确定的类型列表的变体(我正在考虑大量使用预处理器......)? 使用 boost::any 怎么样?其他方法? (野指针?)

TIA ~阿基

更正:预处理器在这种情况下不可用。

【问题讨论】:

  • std::vector 可能是最简单的。只是不要改变大小。 :) 诚然,它并不完全相同,但它很干净。
  • 是的,好吧,我已经有一个使用 std::vector 而不是 tr1::array 的实现,但是使用动态大小是没有意义的,因为它们可以在编译时计算,所以我在寻找用于静态解决方案。
  • 您可能会喜欢以下容器之一:boost.org/doc/libs/1_43_0/libs/fusion/doc/html/fusion/…。另外,如果您想回复某人,请使用@,例如@aaa
  • 就像@aaa 所说,您需要使用融合。我实际上有一个与此类似的问题,它会生成不同类型的数组,here

标签: c++ boost c++11


【解决方案1】:

我会使用 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 似乎是解决方案 :) 谢谢。
  • 我总是很高兴看到有关使用一些恕我直言“高级”(或者可能只是“新”)boost 库(如 mpl/fusion/proto/phoenix)的帖子。有时我希望有更多关于伟大用例的帖子(甚至有一些关于此的问题,但没有太多答案)。但是谢谢你的例子!
【解决方案2】:

您可以将不同类型的类放入 STL 容器的唯一方法是容器包含指向某些基本类型的指针(引用不起作用,因为它们不是默认可构造的)并且您要收集的所有对象都继承自那种。请注意,从基类继承的类型的容器(或任何模板类)不会从基类型的容器继承。你可以只使用 void* 但你需要做很多丑陋和危险的铸造,你必须记住自己释放内存。为什么不编写一个固定大小的数组类,让您可以在构造函数中设置大小?如果您将其编写为 araray 的包装器,则工作量不会太大。如果你想使用一些基于智能指针的解决方案,不要试图使用 auto_ptr,因为 STL 容器的复制语义是错误的 - 使用 boost shared_ptr 之类的东西。

【讨论】:

    【解决方案3】:

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

    您的选择是:

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

    • 在集合中存储指向数组的指针和数组的大小。这可能类似于:std::vector&lt;std::pair&lt;int *, size_t&gt; &gt;。只要确保数组的生命周期至少与向量的生命周期一样长!

    • 我希望 boost::variant 也能正常工作,但在实践中使用起来会相当繁琐。

    boost::variant&lt;array&lt;int, 2&gt;, array&lt;int, 4&gt;, array&lt;int, 6&gt;, ... &gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2013-06-18
      • 2015-11-25
      • 2021-08-11
      • 1970-01-01
      相关资源
      最近更新 更多