long double vector


I'd like to perform some calculations on a vector of long double. The calculations should only be performed once. To solve the problem, I've created a private class LongDouble that sets a flag when a long double value is set. Each result of a calculation, for example min, is then defined as a LongDouble. I get compile errors, as shown below.

The code I've come up with thus far is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

class tester {
  private:
    std::vector<long double> vld;

    struct LongDouble {
      public:
        void operator = (const long double newVal) {
          value_ = newVal;
          isSet_ = true;
        }

        operator long double() { return value_; }
        bool isSet() { return isSet_; }

      private:
        mutable bool isSet_{ false };
        long double value_;
    };

    LongDouble min;
    LongDouble max;
    LongDouble sum;

    inline const LongDouble & calc_sum() const {
      if (!sum.isSet())
        sum = std::accumulate(begin(vld), end(vld), 0.0);
      return sum;
    }

  public:
    explicit tester( const std::vector<long double> & test_sample ): vld{ test_sample } { }
    ~tester() { }
    inline LongDouble range()    const { return max-min; }
    inline LongDouble midrange() const { return (max+min)/2; }
    inline LongDouble mean()     const { return calc_sum() / vld.size(); }
};

int main() {
  tester a { 7.0, 9.1, 8.3, 65.1, 23.01 };
  cout << a.min() << " " << a.max() << " " << a.mean() << std::endl;
  return 0;
}


I get the following compile error:
1
2
3
4
5
6
7
8
9
10
11
12
13
c++ -g -std=c++14 -pedantic -Wall -Wpointer-arith -Wwrite-strings -Wcast-qual -Wcast-align -Wformat-security -Wformat-nonliteral -Wmissing-format-attribute -Winline -funsigned-char "test_long_double.cpp" (in directory: /c++/tester)
test_long_double.cpp: In member function ‘const tester::LongDouble& tester::calc_sum() const’:
test_long_double.cpp:30:22: error: passing ‘const tester::LongDouble’ as ‘this’ argument discards qualifiers [-fpermissive]
       if (!sum.isSet())
                      ^
test_long_double.cpp:18:14: note:   in call to ‘bool tester::LongDouble::isSet()’
         bool isSet() { return isSet_; }
              ^
test_long_double.cpp:31:13: error: passing ‘const tester::LongDouble’ as ‘this’ argument discards qualifiers [-fpermissive]
         sum = std::accumulate(begin(vld), end(vld), 0.0);
             ^
test_long_double.cpp:12:14: note:   in call to ‘void tester::LongDouble::operator=(long double)’
         void operator = (const long double newVal) {


Could anybody suggest a fix(es) ?
Thanks
Last edited on
Line 17/18: Add const to the functions.
Line 21: mutable is not necessary. Better remove it.
Line 29: Either you remove const for this function or you declare sum as mutable.

thanks, that works when setting min & max, but when attempting to perform a calculation on the result of min & max, say for example "range", I get an implicit type conversion.

I have however defined range as type LongDouble as well, so I'm not sure why the error? Could you help explain?

error is:
 
test_long_double.cpp:50:50: error: could not convert ‘(tester::maximum().tester::LongDouble::operator long double() - tester::minimum().tester::LongDouble::operator long double())’ from ‘long double’ to ‘tester::LongDouble’


modified code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

class tester {
  private:
    std::vector<long double> vld;
    struct LongDouble {
      public:
        void operator = (const long double newVal) {
          value_ = newVal;
          isSet_ = true;
        }

        operator long double() { return value_; }
        bool isSet() { return isSet_; }

      private:
        mutable bool isSet_{ false };
        long double value_;
    };
    
    LongDouble min;
    LongDouble max;
    LongDouble sum;

    inline LongDouble & calc_sum() {
      if (!sum.isSet())
        sum = std::accumulate(begin(vld), end(vld), 0.0);
      return sum;
    }

  public:
    tester( const std::vector<long double> & test_sample ): vld{ test_sample } { }
    ~tester() { }

    inline LongDouble minimum() {
      if (!min.isSet())
        min = *std::min_element(std::begin(vld), std::end(vld));
      return min;
    }

    inline LongDouble maximum() {
      if (!max.isSet())
        max = *std::max_element(std::begin(vld), std::end(vld));
      return max;
    }

    inline LongDouble range() { return maximum() - minimum(); }
    // inline LongDouble && midrange() const { return ( maximum() + minimum() ) / 2; }
    // inline LongDouble && mean()     const { return calc_sum() / vld.size(); }
};

int main() {
  vector<long double> v { 7.0, 9.1, 8.3, 65.1, 23.01 };
  tester a {v};
  cout << a.minimum() << " " << a.maximum() << " " << a.range() << std::endl;
  return 0;
}

The operator =(...) can only be used for existing objects. On line 50 however you try to create a new temporary LongDouble object. This requires that the constructor accepts long double.

So either you add a constructor that accepts long double or you overload the operator-(...) which returns LongDouble. Or you create a local variabe in range() where you assign the result of the operation.
Topic archived. No new replies allowed.