Шаблон класса минималистичный умный массив (контейнер) - PullRequest
0 голосов
/ 03 мая 2010

Я написал шаблон класса-контейнера (массива) (назовем его умный массив ) для использования его на платформе BREW (которая не позволяет использовать многие конструкции C ++, такие как библиотека STD, исключения и т. Д. . Имеет очень минимальную поддержку времени выполнения C ++); во время написания этой статьи мой друг сказал, что что-то подобное уже существует в Boost под названием MultiArray , я пробовал это сделать, но компилятор ARM (RVCT) плачет с сотнями ошибок. Я не видел источник Boost.MultiArray, я начал изучать шаблоны только недавно; шаблонное метапрограммирование меня очень интересует, хотя я не уверен, является ли он строго таким, который можно классифицировать таким образом.

Поэтому я хочу, чтобы все мои коллеги-поклонники C ++ рассмотрели это - указали на недостатки, потенциальные ошибки, предложения, оптимизации и т. Д .; что-то вроде «Вы не написали свою собственную Большая тройка , которая может привести к ...». Возможно, любая критика, которая поможет мне улучшить этот класс и, следовательно, мои навыки C ++.

Редактировать: Я использовал std::vector, поскольку это легко понять, позже он будет заменен пользовательским письменным шаблоном векторного класса, созданным для работы на платформе BREW. Также C ++ 0x связанный синтаксис, такой как static_assert, также будет удален в конечном коде.

smart_array.h

#include <vector>
#include <cassert>
#include <cstdarg>
using std::vector;

template <typename T, size_t N>
class smart_array
{
    vector < smart_array<T, N - 1> > vec;

public:
    explicit smart_array(vector <size_t> &dimensions)
    {
        assert(N == dimensions.size());

        vector <size_t>::iterator it = ++dimensions.begin();
        vector <size_t> dimensions_remaining(it, dimensions.end());

        smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
        vec.assign(dimensions[0], temp_smart_array);
    }

    explicit smart_array(size_t dimension_1 = 1, ...)
    {
        static_assert(N > 0, "Error: smart_array expects 1 or more dimension(s)");
        assert(dimension_1 > 1);

        va_list dim_list;
        vector <size_t> dimensions_remaining(N - 1);

        va_start(dim_list, dimension_1);
            for(size_t i = 0; i < N - 1; ++i)
            {
                size_t dimension_n = va_arg(dim_list, size_t);
                assert(dimension_n > 0);
                dimensions_remaining[i] = dimension_n;
            }
        va_end(dim_list);

        smart_array <T, N - 1> temp_smart_array(dimensions_remaining);
        vec.assign(dimension_1, temp_smart_array);
    }

    smart_array<T, N - 1>& operator[](size_t index)
    {
        assert(index < vec.size() && index >= 0);
        return vec[index];
    }

    size_t length() const
    {
        return vec.size();
    }
};

template<typename T>
class smart_array<T, 1>
{
    vector <T> vec;

public:
    explicit smart_array(vector <size_t> &dimension) : vec(dimension[0])
    {
        assert(dimension[0] > 0);
    }

    explicit smart_array(size_t dimension_1 = 1) : vec(dimension_1)
    {
        assert(dimension_1 > 0);
    }

    T& operator[](size_t index)
    {
        assert(index < vec.size() && index >= 0);
        return vec[index];
    }

    size_t length()
    {
        return vec.size();
    }
};

Пример использования:

#include "smart_array.h"
#include <iostream>
using std::cout;
using std::endl;

int main()
{
    // testing 1 dimension
    smart_array <int, 1> x(3);
    x[0] = 0, x[1] = 1, x[2] = 2;
    cout << "x.length(): " << x.length() << endl;

    // testing 2 dimensions
    smart_array <float, 2> y(2, 3);
    y[0][0] = y[0][1] = y[0][2] = 0;
    y[1][0] = y[1][1] = y[1][2] = 1;
    cout << "y.length(): " << y.length() << endl;
    cout << "y[0].length(): " << y[0].length() << endl;

    // testing 3 dimensions
    smart_array <char, 3> z(2, 4, 5);
    cout << "z.length(): " << z.length() << endl;
    cout << "z[0].length(): " << z[0].length() << endl;
    cout << "z[0][0].length(): " << z[0][0].length() << endl;
    z[0][0][4] = 'c'; cout << z[0][0][4] << endl;

    // testing 4 dimensions
    smart_array <bool, 4> r(2, 3, 4, 5);
    cout << "r.length(): " << r.length() << endl;
    cout << "r[0].length(): " << r[0].length() << endl;
    cout << "r[0][0].length(): " << r[0][0].length() << endl;
    cout << "r[0][0][0].length(): " << r[0][0][0].length() << endl;

    // testing copy constructor
    smart_array <float, 2> copy_y(y);
    cout << "copy_y.length(): " << copy_y.length() << endl;
    cout << "copy_x[0].length(): " << copy_y[0].length() << endl;

    cout << copy_y[0][0] << "\t" << copy_y[1][0] << "\t" << copy_y[0][1] << "\t" << 
        copy_y[1][1] << "\t" << copy_y[0][2] << "\t" << copy_y[1][2] << endl;

    return 0;
}

1 Ответ

1 голос
/ 05 мая 2010

Если я понимаю, что вы хотите от этого типа:

Короче, было бы оптимально использовать форму:

template < typename T_, unsigned N_ ><br> struct t_array {<br> /* ... */<br> static const size_t Size = N_; typedef T_ T;<br> T objects_[Size];<br> };

по многим причинам , если , вам нужен только фиксированный размер и массив фиксированного типа. Компилятор может сделать много безопасных предположений - в некоторых случаях для меня размер объекта уменьшен до 20% (по сравнению с использованием std :: vector). Это также быстрее, безопаснее. Если вы используете их повсюду, то вы можете в конечном итоге создать намного большие двоичные файлы (по сравнению с использованием std :: vector).

Есть класс <boost/array.hpp>, который вы должны прочитать.

Извините, если вы не находите это полезным - я думаю, что чтение по крайней мере одной общей реализации качества производства (прежде чем углубляться в новые технологии) поможет.

...