c++ - C++11 中不同类型对象的 std::array 替代方案

标签 c++ arrays c++11 memory-management

我正在寻找关于如何组织和访问我的数据的更好的解决方案。
我的数据是一组结构(在下面的示例中为 _array_10_array_20),其中包含 std::array不同尺寸(见下文my_data)。
理想情况下,我想访问它,因为它是具有不同长度的结构数组,但这是不允许的,因为不同的长度是不同的类型。
我在下面的解决方案有效,但我发现它非常难看(特别是 void * 的数组)。

Q1。关于如何拥有更安全、更高效/便携或至少不那么丑陋的解决方案的任何想法?
Q2。没有模板的建议解决方案是否可移植?它依赖于长度存储在其余数据之前的事实,因为将指针转换为长度错误的对象会弄乱对可变长度第一个字段之后的所有字段的访问。

我的限制包括:

  • C++11
  • 标准库
  • 没有 std::vector
  • 内存使用使我无法简单地分配 my_data 的数组最大可能长度
  • 大部分数据( _array_10_array_20 等)将被放置在专门为其保留的内存区域中

  • 使用 data_view 和 template 需要在构建时了解数组的长度。如果我们能避免它,那就太好了。
  • 已编辑问题以包含 Guillaume Racicot
  • 提出的解决方案
    #include <iostream>
    #include <array>
    
    std::array<void *, 2> _ptrs;
    
    template <int length>
    struct my_data
    {
        int                     array_length;
        std::array<int, length> something;
        std::array<int, length> data;
        my_data()
        {
            array_length = length;
        }
    };
    
    
    struct my_data_view
    {
        int         array_length;
        const int * something;
        const int * data;
    
        template <int length>
        my_data_view(my_data<length> const & data_in) :
            array_length(length),
            something(data_in.something.data()),
            data(data_in.data.data())
        {}
    };
    
    template <int length>
    void
    print_element(int array_idx, int element)
    {
        my_data<length> * ptr = reinterpret_cast<my_data<length> *>(_ptrs[array_idx]);
    
        std::cout << "array " << length << ", data[" << element << "] = " << ptr->data[element] << ".\n";
    }
    
    void
    print_element(int array_idx, int element)
    {
        my_data<1> * ptr    = reinterpret_cast<my_data<1> *>(_ptrs[array_idx]);
        int          length = ptr->array_length;
    
        int data_to_print = 0;
        switch (length)
        {
            case 10:
            {
                data_to_print = reinterpret_cast<my_data<10> *>(_ptrs[array_idx])->data[element];
                break;
            }
            case 20:
            {
                data_to_print = reinterpret_cast<my_data<20> *>(_ptrs[array_idx])->data[element];
                break;
            }
        }
        std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
    }
    
    void
    print_element(my_data_view view, int element)
    {
        int length        = view.array_length;
        int data_to_print = view.data[element];
    
        std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
    }
    
    int
    main()
    {
        my_data<10> _array_10;
        my_data<20> _array_20;
    
        _ptrs[0] = static_cast<void *>(&_array_10);
        _ptrs[1] = static_cast<void *>(&_array_20);
    
        _array_10.data[5] = 11;
        _array_20.data[5] = 22;
    
        std::cout << "using template\n";
        print_element<10>(0, 5);
        print_element<20>(1, 5);
    
        std::cout << "\nwithout template\n";
        print_element(0, 5);
        print_element(1, 5);
    
        std::cout << "\nusing data_view\n";
        print_element(my_data_view(_array_10), 5);
        print_element(my_data_view(_array_20), 5);
    }
    

    最佳答案

    您可以创建一个不分配的动态 View 类:

    struct my_data_view
    {
        int array_length;
        std::span<int> something;
        std::span<int> data;
    
        template<int length>
        my_data_view(my_data<length> const& data) : 
            array_length{length}, something{data.something}, data{data.data}
        {}
    };
    

    跨度只是一个指针和一个大小。如果您无权访问 std::span (来自 C++20)您可以简单地将这些成员替换为 int*并使用 array_length为大小。

    这个my_data_view类型是这样使用的:
    void
    print_element(my_data_view view, int element)
    {
        int length = view.array_length;
        int data_to_print = view.data[element];
    
        std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
    }
    

    这是与 std::span 一起使用的代码和简单的int* .

    关于c++ - C++11 中不同类型对象的 std::array 替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60263522/

    相关文章:

    c++ - 使用了未初始化的局部变量?

    c++ - 在 C++ 插件中卸载静态实例变量?

    c++ - windows xp 修改时区

    C++如何正确计算const char中的字符?

    python - 检查python中两个字符串之间的交集

    c++ - C++假设

    c++ - 初始化 vector 的 vector (外部 vector 和内部 vector )

    javascript - 通过仅选择其属性的一部分,从另一个对象数组构建一个对象数组

    c++ - 如何在 C++ 中使用右值引用来避免不必要的实例

    c++ - 为什么 uintptr_t 和 intptr_t 在 C(和 C++)标准中是可选类型?