Я хотел бы построить модульный арифметический класс с эффективным пространством. Идея состоит в том, что модуль M является неизменным атрибутом, который фиксируется во время создания экземпляра, поэтому, если у нас есть большой массив (std :: vector или другой контейнер) значений с тем же M, M нужно хранить только один раз.
Если M можно исправить во время компиляции, это можно сделать с помощью шаблонов:
template <typename num, num M> class Mod_template
{
private:
num V;
public:
Mod_template(num v=0)
{
if (M == 0)
V = v;
else
{
V = v % M;
if (V < 0)
V += M;
}
}
// ...
};
Mod_template<int, 5> m1(2); // 2 mod 5
Однако в моем приложении мы должны иметь возможность выражать M времени выполнения. Что у меня выглядит так:
template <typename num> class Mod
{
private:
const num M;
num V;
public:
Mod(num m, num v=0): M(abs(m))
{
if (M == 0)
V = v;
else
{
V = v % M;
if (V < 0)
V += M;
}
}
// ...
};
Mod<int> m2(5, 2); // 2 mod 5
Mod<int> m3(3); // 0 mod 3
Это работает, но большой вектор значений mod M использует в 2 раза больше места, чем нужно.
Я думаю, что основная концептуальная проблема заключается в том, что мод различных модулей синтаксически одного типа, даже если они «должны» быть разных типов. Например, заявление типа
m2 = m3;
должен вызывать ошибку времени выполнения «естественно» (в моей версии это происходит «вручную»: проверка встроена в конструктор копирования, а также в каждый бинарный оператор, который я реализую).
Итак, есть ли способ реализовать некоторую динамическую типизацию, чтобы тип объекта Mod запоминал модуль? Буду очень признателен за любую идею, как решить эту проблему.
Для меня это повторяющаяся проблема с различными математическими структурами (например, хранение множества перестановок в одном наборе, элементов одной группы и т. Д.)
РЕДАКТИРОВАТЬ: насколько я понимаю,
шаблоны — это типы, параметризованные классом или литералом.
что я хочу: тип, параметризованный const-объектом (const num
в этом случае, const Group&
или же const Group *const
для групп и т. д.).
Это возможно?
Это будет трудно сделать в нулевом объеме памяти, если класс должен знать, что M
должно быть без посторонней помощи. Вероятно, лучшее, что вы можете сделать, это сохранить указатель на общий M
что может быть немного лучше, в зависимости от того, насколько большой num
является. Но это не так хорошо, как бесплатно.
Это будет легче спроектировать, если M
является переданным значением для всех функций, которые в нем нуждаются. Затем вы можете сделать такие вещи, как создать пул объектов, которые все имеют одинаковые M
(Есть много простых способов создать это; например, map<num, vector<num> >
) и только магазин M
один раз для бассейна. Звонящий должен знать, какой пул Mod
объект пришел, но это, вероятно, что-то, что он все равно знает.
Трудно ответить на этот вопрос совершенно изолированно … знание о вызывающем коде определенно поможет вам получить лучшие ответы.