Click here to Skip to main content
15,881,588 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a vector of objects and I need to form their sum however there is no default value for the type of object I am summing so I do not see how to initialize the sum without declaring it std::optional<object_type> sum; just prior to the loop over the vector. So my question is there a way to perform the sum without utilizing this form of seemingly objectionable programming which leaves a variable uninitialized prior to use. Thank you kindly

What I have tried:

I tried assigning the sum as the return of a lambda but found that the lambda faced the same problem as it too had to declare std::optional<object_type> sum; prior to the loop.

Here is the class :
C++
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) // 
Posted
Updated 7-Aug-20 7:11am
v3
Comments
Richard MacCutchan 6-Aug-20 15:14pm    
It is not clear what the problem is, and what value you are summing from the objects. Why do you need sum to be optional?
BernardIE5317 6-Aug-20 15:45pm    
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 6-Aug-20 16:14pm    
Sorry, but I am a bit lost and don't understand what the problem is with a start point of 0. Or, in fact, if you don't want to use that value, then make sure it is not in the vector. I may be missing something obvious here, for which I apologise.

Can I suggest you update your question with some example code to give a better idea of what you are trying to achieve?
BernardIE5317 6-Aug-20 16:23pm    
The "zero" value is never in the vector. In normal arithmetic addition the initial value of a sum would of course be 0 (zero) but there is no "zero" value for class cinterval unless I construct such a special case but of course in programming special cases are to be avoided. Thank you kindly Cheerios
[no name] 6-Aug-20 17:50pm    
agree

1 solution

I would say you are stuck between a rock and a hard place. You keep stating it can't have an initial value but it HAS to. Otherwise your will class will not operate correctly. This is why :
C++
this_type& operator += (const interval_type& rhs)
{
    assert(contiguous(*this, rhs));
    if (*this < rhs) high = rhs.high;
    else low = rhs.low;
    return *this;
}
It HAS to have a value to compare the rhs with. If this just will not work for you then add a boolean flag to state whether it has ever been assigned. if not then at the first comparison skip it and assign the value. The logic would then become this :
C++
this_type& operator += (const interval_type& rhs)
{
    assert(contiguous(*this, rhs));
    if( assigned )
    {
        if( *this < rhs )
             high = rhs.high;
        else
             low = rhs.low;
    }
    else
    {
        high = rhs.high;
        low = rhs.low;
        assigned = true;
    }
    return *this;
}
I have no idea whether that logic would work but you have few other options for dealing with this.
 
Share this answer
 
Comments
Stefan_Lang 10-Aug-20 7:27am    
Agreed. The interval needs a 'default' value simply because the input vector may be empty! In that case the result cannot be any regular interval!

[edit]removed the last part as it doesn't apply to integer intervals[/edit]

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900