Сформируйте сумму объектов, которая не имеет значения по умолчанию
У меня есть вектор объектов и мне нужно сформировать их сумму однако нет значения по умолчанию для типа объекта который я суммирую поэтому я не вижу как инициализировать сумму не объявляя ее
std::optional<object_type> sum;
непосредственно перед петлей над вектором. Поэтому мой вопрос заключается в том, есть ли способ выполнить сумму без использования этой формы, казалось бы, нежелательного программирования, которое оставляет переменную неинициализированной перед использованием. Большое вам спасибоЧто я уже пробовал:
Я попытался присвоить сумму как возврат лямбды, но обнаружил, что лямбда столкнулась с той же проблемой, что и она тоже должна была объявить
std::optional<object_type> sum;
до начала цикла.Вот этот класс :
template<typename numericType> MAKERCLASS(cinterval) { public: using numeric_type = numericType; using this_type = cinterval<numeric_type>; FRIENDINSERTION(cinterval) using interval_type = this_type; numeric_type low, high; cinterval(numeric_type _low, numeric_type _high) : low(_low), high(_high) { ASSERTINVARIANT(DATANAMEVALUEA(_low), DATANAMEVALUEA(_high)); } numeric_type begin() const { return low; } numeric_type end() const { return high +1; } numeric_type width() const { return high +1 - low; } bool operator < (const interval_type& rhs) const { return high < rhs.low; } bool operator > (const interval_type& rhs) const { return rhs.high < low; } bool operator == (const interval_type& rhs) const { return low == rhs.low && high == rhs.high; } bool operator != (const interval_type& rhs) const { return !operator == (rhs); } this_type& operator += (const interval_type& rhs) { assert(contiguous(*this, rhs)); if (*this < rhs) high = rhs.high; else low = rhs.low; return *this; } void shift_right(numeric_type d) { low += d; high += d; } void shift_left(numeric_type d) { low -= d; high -= d; } bool assert_invariant() const { return low <= high; } TOBASICOSTREAMSIGNATURE { TOBASICOSTREAMPREAMBLE auto lbracket = get_left_bracket<char_type>(); auto rbracket = get_right_bracket<char_type>(); auto lparen = get_left_paren<char_type>(); auto rparen = get_right_paren<char_type>(); DELIMITERCOLOR << lbracket; INTERVALCOLOR << XFormatNumber<char_type>(low); CONSOLEDEFAULTCOLOR(bos) << space; INTERVALCOLOR << XFormatNumber<char_type>(high); DELIMITERCOLOR << rbracket; DELIMITERCOLOR << lparen; INTERVALCOLOR << XFormatNumber<char_type>(width()); DELIMITERCOLOR << rparen; CONSOLEDEFAULTCOLOR(bos); } static bool overlap(const interval_type& lhs, const interval_type& rhs) { return lhs.low <= rhs.high && rhs.low <= lhs.high; } static bool overlap(numeric_type lhs, const interval_type& rhs) { return lhs >= rhs.low && lhs <= rhs.high; } static bool contiguous(const interval_type& lhs, const interval_type& rhs) { return lhs.high + 1 == rhs.low || rhs.high + 1 == lhs.low; } // ---lhs--- // | | // ------- | [1] case // ------------ [2] // --------------- [3] // --- | [4] // --------- [5] // ------------ [6] // | --- | [7] // | ------ [8] // | --------- [9] enum overlap_case_etype { overlap_case_1 = 1, overlap_case_2, overlap_case_3, overlap_case_4, overlap_case_5, overlap_case_6, overlap_case_7, overlap_case_8, overlap_case_9 }; static overlap_case_etype OVERLAPCASE(const interval_type& lhs, const interval_type& rhs) { overlap_case_etype overlap_case = [&]() { if(lhs.low < rhs.low) // [7] [8] [9] { if(lhs.high < rhs.high) // [9] return interval_type::overlap_case_9; else if(lhs.high == rhs.high) // [8] return overlap_case_8; else // [7] return overlap_case_7; } else if(lhs.low == rhs.low) //
Richard MacCutchan
Непонятно, в чем проблема, и какое значение вы суммируете из объектов. Зачем вам это нужно sum
быть необязательным?
PaltryProgrammer
Thank you for your response. The object which I am summing by overloading operator += is an interval for example class cinterval { int m_min; int_m_max; } I wish to form the sum of contiguous such intervals by which I mean constructing a new interval which is the union of the two with the required m_min and m_max values. I prefer to avoid a special value of {0, 0} as it would need to specially and separately considered in any and all cinterval operations which would lead to inelegant and error prone code. In particular to perform such a sum with an initial {0,0} sum the code can not merely assign the m_min and m_max as it otherwise would instead it would need to examine the initial sum on each addition to determine if it is of this special kind. For example if the first term in the vector was { 10, 100 } the result of naively summing it would be { 0, 100 } which would not be correct as the correct value is merely the first non-"zero" term i.e. { 10, 100 }. So I do not know how to construct a "zero" valued interval This is why I am currently utilizing std::optional Thank you kindly
Richard MacCutchan
Извините, но я немного заблудился и не понимаю, в чем проблема с начальной точкой 0. или, на самом деле, если вы не хотите использовать это значение, то убедитесь, что его нет в векторе. Возможно, я упускаю что-то очевидное, за что приношу свои извинения.
Могу ли я предложить вам обновить свой вопрос с помощью некоторого примера кода, чтобы дать лучшее представление о том, чего вы пытаетесь достичь?
PaltryProgrammer
"Нулевое" значение никогда не находится в векторе. При обычном арифметическом сложении начальное значение суммы, конечно, было бы 0 (ноль), но для класса cinterval нет "нулевого" значения, если только я не построю такой частный случай, но, конечно, в программировании особых случаев следует избегать. Спасибо группе поддержки
Rajeev.Bera
согласен
0x01AA
Цитата: "У меня есть вектор объектов, и мне нужно сформировать их сумму":
Пожалуйста, объясните, что такое "сумма объектов"... На самом деле не существует "суммы объектов"
PaltryProgrammer
Под "суммой" я подразумеваю перегрузку оператора += на этот тип объекта, то есть класс cinterval, как описано выше. Если вы хотите, вы можете думать о "сумме" как о любом двоичном операторе, определенном для типа в данном случае class cinterval. Однако нет никакого значения идентичности, если это правильный термин, который я знаю для этого класса, который допускает инициализацию суммы, как это было бы в противном случае для простой арифметики нуля, и в этом заключается суть моей проблемы, которая заключается в том, что текущая версия полагается на std::optional<cinterval> sum; в качестве начального значения. Спасибо группе поддержки
Richard MacCutchan
Это все еще не проясняет ситуацию. Реализации operator+=
на любом классе это довольно простой процесс, вам просто нужно начать с объекта, значения которого равны нулю. После добавления следующего в вектор значения будут "чем-то". Так что я все равно не понимаю, зачем вам это нужно. std::optional
в качестве отправной точки. Как я уже говорил, нам нужно увидеть некоторый код, особенно определение вашего класса объектов.
Stefan_Lang
Я согласен с Риком Йорком (Решение 1), что у вас должно быть значение по умолчанию. Математически интервал-это множество всех чисел из заданного базового множества (целые числа, вещественные числа и т. д.), которые удовлетворяют условию нахождения в заданных границах. Пустое множество * - это допустимое множество и допустимый интервал. Поэтому ваш класс должен быть способен представлять пустой интервал.
Еще одна вещь: не объявляйте переопределения для операторов сравнения (<, <=, > и >=), если только набор всех интервалов не является полностью упорядоченным набором с этим определением. Ваше определение не удовлетворяет этому условию, так как вы можете иметь два интервала, которые не меньше, не больше и не равны! Опасно определять operator<, потому что он подразумевает строгий порядок и допускает такие вещи, как вызов std::sort. Однако вызов сортировки может дать вам разные результаты для одного и того же набора интервалов, если вы передадите эти интервалы в другом порядке!
Если вы используете какое-то сравнение меньше/больше, используйте обычную функцию или метод, а не переопределение оператора.
P.S.: Если вам нужен действительный оператор<, то он должен быть определен таким образом, чтобы он удовлетворял следующим условиям:
а&ЛТ;б &амп;&амп; б&л;с ==&ГТ; а&ЛТ;в
символом>б &ЛТ;==&ГТ; б&ЛТ;а
а==б &ЛТ;==&ГТ; !а&ЛТ;Б &&усилителя;!б&ЛТ;а
а==б &амп;&амп; в==с &ЛТ;==&ГТ; а=в=с
Это третье условие, которое нарушает вашу реализацию.