Как определить размер массива, который является статическим членом нереализуемого класса?

Я пишу класс, который не хочу создавать. Все его члены статичны. Этот класс представляет собой периферийное устройство микроконтроллера. Поскольку в микроконтроллере есть только один экземпляр этого периферийного устройства, мне не имеет смысла создавать экземпляры этого класса. Класс группирует только данные и функции этого периферийного устройства.

Один из элементов данных класса - это массив, размер которого пользователь класса должен определить во время компиляции. Если бы я мог создавать объекты этого класса, я бы мог инициализировать константы в списке инициализаторов конструктора, но я действительно не хочу создавать экземпляры этого класса. Возможно, я мог бы использовать шаблоны и установить размер массива в качестве параметра шаблона, но мне нужно было бы использовать что-то вроде my_class<5>::do_something() для каждого вызова члена. Есть ли более простой способ решить эту проблему? Я бы хотел сделать свой класс примерно таким:

class my_class
{
private:
    static const int _size;
    static int _array[_size];
public:
    static void array_size(int size) { _size = size; }
    static void do_something() { /* .... */ } 
};

person Community    schedule 01.01.2017    source источник
comment
Если размер установлен во время компиляции, что static void array_size(int size) { _size = size; } должно делать?   -  person wally    schedule 01.01.2017
comment
Рассмотрим одноэлементный класс. У него есть некоторые преимущества перед простыми старыми статическими данными.   -  person n. 1.8e9-where's-my-share m.    schedule 01.01.2017
comment
@ n.m., можете ли вы поподробнее рассказать?   -  person    schedule 01.01.2017


Ответы (4)


Рассмотрите возможность использования шаблона класса, параметризованного размером массива constexpr, а затем создайте псевдоним:

#include <array>

template <std::size_t Size>
class my_class_impl {
private:
    static constexpr std::size_t size = Size;
    static std::array<int, Size> arr;
public:
    static void do_something() { /* .... */ }
};

template <std::size_t Size>
std::array<int, Size> my_class_impl<Size>::arr;

using my_class = my_class_impl<10>;

int main() {
    my_class::do_something();
}
person W.F.    schedule 01.01.2017

Ваш лучший выбор, вероятно, будет старым добрым определением.

Вот как я бы это структурировал (используя пространства имен, поскольку это идиоматический способ создания статических классов):

периферийный.h:

namespace peripheral {
  void do_something();
}

периферийный.cpp:

#ifndef PERIPH_ARRAY_SIZE
#  error "please define the size of array"
#endif

namespace {
  int _array[PERIPH_ARRAY_SIZE];
}

namespace peripheral {
  void do_something() {...}
}
person Frank    schedule 01.01.2017

Один из способов разрешить пользователю устанавливать размер - это изменить массив на вектор. Поскольку это личное, вы контролируете, как его использовать. Простое bool ограничит его размер один раз и убедится, что он действительно увеличивается:

class my_class
{
private:
    static const int _size = 10;
    static vector<int> _array;
    static bool arraySized;
public:
    static void array_size( int size = _size ) 
    {
        if ( !arraySized )
        {
            _array = vector<int>( size );
            arraySized = true;
        }
    }
    static void do_something() 
    {
        if ( arraySized )
        {
            /* .... */
        }
    }
};

Хотя это не во время компиляции, он имеет тот же эффект.

Еще пара вещей, о которых стоит подумать. Использование подхода на основе шаблонов может позволить создать более 1 экземпляра этого класса. Что может нарушить принцип сингулярности, который вам кажется

using my_class = my_class_impl<10>;

using my_class2 = my_class_impl<20>;
int main() {
    my_class::do_something();
    my_class2::do_something();
}

Другое дело, что новейший фреймворк Atmel включает заголовки для векторов. Информация, на которую вы ссылаетесь, должна быть устаревшей.

person tinstaafl    schedule 01.01.2017
comment
Спасибо, но у меня нет библиотеки C ++ std - это платформа, над которой я работаю. - person ; 01.01.2017
comment
Если у вас нет библиотеки C ++ std, какую библиотеку вы используете? - person tinstaafl; 01.01.2017
comment
Я программирую микроконтроллер Atmel AVR. Для этой платформы нет официальной библиотеки C ++. - person ; 01.01.2017
comment
Итак, если вы используете Atmel Studio, вы сможете использовать все, что есть в библиотеке C ++ std. векторы являются частью библиотеки C ++ std. Это просто вопрос включения правильного заголовка. - person tinstaafl; 01.01.2017
comment
Я добавил для вас больше информации. - person tinstaafl; 02.01.2017
comment
Спасибо! Не могли бы вы указать источник этой информации? Я поискал в Интернете и, похоже, ничего об этом нет. - person ; 04.01.2017
comment
Я установил Atmel Studio и обнаружил заголовок во включенных папках. Это действительно потребовало немного закопаться. это было #include <c++/5.3.1/vector> - person tinstaafl; 04.01.2017

Ваше главное требование - размер массива должен быть установлен во время компиляции. Это больше C-ish, чего вы обычно избегаете при написании C ++, но в вашем случае может иметь больше смысла использовать макросы, такие как

#define ARRAY_SIZE 
... somewhere in your class ...
static int array_name[ARRAY_SIZE];
person mgarey    schedule 01.01.2017
comment
На самом деле я сейчас использую макросы, но этот класс будет частью библиотеки. Я хотел бы позволить пользователю определять размер массива в коде вместо использования флага -DARRAY_SIZE при компиляции. - person ; 01.01.2017
comment
Просто для пояснения: когда вы говорите «часть библиотеки», вы имеете в виду, что пользователь должен статически связать указанную библиотеку со своим кодом? - person mgarey; 01.01.2017
comment
В этом случае рассмотрите комментарий n.m. в своем вопросе (используя класс Singleton, а не статические члены) - person mgarey; 01.01.2017
comment
не могли бы вы рассказать об этом поподробнее? Я не знаю, как реализовать синглтон. Я также не знаю, каковы преимущества этого подхода вместо моего класса со статическими членами. - person ; 01.01.2017
comment
В этом ответе показано, как реализовать синглтон: stackoverflow.com / questions / 1008019 / c-singleton-design-pattern / - person mgarey; 01.01.2017