代码之家  ›  专栏  ›  技术社区  ›  AkiRoss

不同大小的数组的数组

  •  4
  • AkiRoss  · 技术社区  · 15 年前

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

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

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

    我考虑过使用boost::variant,但是如何用编译时确定的类型列表指定一个variant(我正在考虑大量使用预处理器…)?

    短暂性脑缺血发作 ~z~阿基

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

    3 回复  |  直到 15 年前
        1
  •  3
  •   GManNickG    15 年前

    我会使用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());
    }
    
        2
  •  0
  •   Shane    15 年前

    将不同类型的类放入STL容器的唯一方法是,容器包含指向某个基类型的指针(引用不起作用,因为它们不是默认可构造的),并且要收集的对象都继承自该类型。请注意,从基类继承的类型的容器(或任何模板类)不会从基类型的容器继承。你可以使用void*但是你需要做很多丑陋和危险的铸造,你必须记得自己释放记忆。为什么不编写一个固定大小的数组类,允许您在构造函数中设置大小?如果你用araray作为包装器来写的话,应该不会有太多的工作。如果您想使用一些基于智能指针的解决方案,请不要尝试使用auto\u ptr,因为复制语义对于STL容器来说是错误的,可以使用类似boost shared\u ptr的方法。

        3
  •  0
  •   Richard Wolf    15 年前

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

    您的选择是:

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

    • 我希望boost::variant也能正常工作,但在实践中使用起来会比较麻烦。

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