c++11 user defined literals for units of physical properties - c++

I am trying to learn how to use c++11 user defined literals for units of physical properties. The question is, how do I avoid a mixing of these units. So that (8.0_kg + 8.0_km)--> gives error. any ideas guys? i am new to c++, be kind.
class Mass{
public:
//Mass(){
// cout << "only Mass units allowed in here" << endl;
//}
//~Mass();
long double getWeight(long double a);
double car, house, cat;
private:
long double a;
};
long double Mass::getWeight(long double w) {
cout << "returning argument: " << w << '\n'<< endl;
return 0;
}
long double operator"" _km(long double d) { return d * 1000.0; }
long double operator"" _m (long double d) {return d;}
long double operator"" _cm(long double d) { return d / 100.0; }
long double operator"" _tonne(long double m) { return m * 1000.0 ; }
long double operator"" _kg(long double m) { return m ; }
long double operator"" _lb(long double m) { return m * 0.453592; }
long double getDistance(long double d){
long double starting_d = 61.0_kg;
long double total_d = d + starting_d;
cout << "the distance I have run is: " << total_d << endl;
return 0;
}
int main() {
cout << 6.0_km << endl;
cout << 6.0_km + 3.0_m << endl;
cout << 6.0_km + 3.0_m + 15.0_cm << '\n' << endl;
cout << 8.0_tonne << endl;
cout << 8.0_km + 4.0_kg << endl;
cout << 8.0_km + 4.0_kg + 21.0_lb << '\n' << endl;
long double distance = 5.45_km;
getDistance(distance);
Mass obj1;
obj1.getWeight(13.96_lb);
cout << "This is clearly wrong: "<< 8.0_km + 4.0_kg << endl;
obj1.getWeight(10.96_km); // so is this
}

You need to define your own types, since you can't restrict what a primitive represents.
You can use a "tagged template"1 to avoid repetition of operators and such and keep it type safe.
This can be extended so you get for instance distance * distance = area or speed * time = distance checked by the compiler.
Here's a short example:
template<typename Kind>
struct Value
{
long double value;
Value& operator+= (Value v) { value += v.value; return *this; }
};
template <typename Kind>
Value<Kind> operator+ (Value<Kind> lhs, Value<Kind> rhs) { return lhs += rhs; }
// These types don't need definitions; we only need some unique type names.
struct M;
struct D;
using Mass = Value<M>;
using Distance = Value<D>;
Mass operator"" _kg(long double d) { return { d };}
Mass operator"" _lb(long double d) { return { d * 0.453592 };}
Distance operator"" _km(long double d) { return { d * 1000 };}
Distance operator"" _mile(long double d) { return { d * 1609 };}
int main()
{
// OK
Distance d = 1.2_km + 0.2_mile;
// OK
Mass m = 2.3_kg + 1.4_lb;
// invalid operands to binary expression ('Distance' (aka 'Value<D>')
// and 'Mass' (aka 'Value<M>'))
Distance d2 = 2.4_km + 1.2_kg; // Nope
}
1) I don't think there's an established term in C++, but it's very similar to what Haskell refers to as phantom types.

Create classes representing numeric values of the different units. That's how it's been done since long before C++ 11.
Custom literals can make instantiation more readable, though, because it helps preserve the usual order of number and unit :)
See http://en.cppreference.com/w/cpp/language/user_literal
class MassKg
{
double value;
// public c'tor, numeric operators, &c.
};
// ...
MassKg mass(5.0);
DistanceM distance(3.0);
auto c = mass * distance; // may yield an instance of TorqueKgM, or MomentumKgM, therefore
// explicit functions / methods are preferrable for mixed
// multiplication or division
auto mass2 = mass + MassKg(2.0); // yiels an instance of MassKg
auto invalid = mass + distance; // compile time error

Related

return float when + class

I was trying to take float + objected class and have the result return as float, however, my code just does not work. I am pretty confused. I have added that overload function as a friend to the class. could anyone explain it to me?
With the best regards
#include <iostream>
#include <cstdint>
using namespace std;
#define MAX_NUM_SENSORS 5
enum { INVALID, TEMPERATURE, HUMIDTY };
// The 'Sensors' structure describes a single sensor, it's type and current value.
// type - describes the type of sensor 0 (INVALID), 1 (TEMPERATURE), 2 (HUMIDITY)
// value - the current value of the sensor.
// valid - set to TRUE if the sensor is valid, should default to FALSE until set up.
class Sensors
{
public:
friend ostream& operator <<(ostream&, const Sensors&);
friend float operator+ (float,const Sensors&);
private:
int type;
float value;
bool valid = false;
};
ostream& operator<<(ostream& OutStream, const Sensors& OutComp)
{
OutStream << " Type: " << (OutComp.type == TEMPERATURE ? "Temperature" : "Humidity");
OutStream << " Value: " << OutComp.value << endl;
return OutStream;
}
float operator+ (float adding, const Sensors& added)
{
float sum;
sum = added.value + adding;
return sum;
}
int main()
{
Sensors tested();
float m = 1.2 + tested;
cout << m;
return 1;
}
I ran your code in godbolt
There is some kind of simple fixes.
int main()
{
Sensors tested();
// ^--- remove this parenthesis (or use braces, it's ambigious)
float m = 1.2 + tested;
// ^----- This is a double, change this to "1.2f"
cout << m;
return 1;
}
Decimal values in code is double by default, you need to add the postfix f to specify that it is a float. Or you could add a definition of operator + with double as a parameter.
Here is a compiling version of your code

Trying to Understand the behavior of my class objects

Please help me in understanding the following 5 lines of code. What the difference between these two
comp3.AddBoth(comp1, comp2); //this 1 ) give 0 0 but why
comp3.Show();
and
comp3 = comp3.AddBoth(comp1,comp2); //this 2) give 6 + 12i which is the correct answer but why
comp3.Show();
Full code:
#include<iostream>
class ComplexNumber
{
private:
int m_r = 0;
float m_i = 0.0f;
public:
ComplexNumber()
{
}
ComplexNumber(int real, float imagi)
{
m_r = real;
m_i = imagi;
}
void Show()
{
std::cout << " Real and imaginary equation is " << m_r << " + " << m_i << "i " << std::endl << std::endl;
}
ComplexNumber AddBoth( ComplexNumber c1, ComplexNumber c2)
{
int re;
float img;
re = c1.m_r + c2.m_r;
img = c1.m_i + c2.m_i;
ComplexNumber temp(re,img);
return temp;
//std::cout << " Real and imaginary equation is " << re << " + " << img << "i " << std::endl << std::endl;
}
};
int main()
{
ComplexNumber comp1(2, 4), comp2(4, 8), comp3;
comp1.Show();
comp2.Show();
comp3.AddBoth(comp1, comp2); //this 1 ) give 0,0 but why
comp3.Show();
// what the difference between these two
comp3 = comp3.AddBoth(comp1,comp2); //this 2) give 6 + 12i which is the correct answer but why
comp3.Show();
std::cin.get();
//return 0;
}
//#include<iostream>
//
//class ComplexNumber
//{
//
//private:
// int r;
// float i;
//
//public:
// ComplexNumber()
// {
// }
// ComplexNumber(int a, float b)
// {
// r = a;
// i = b;
// }
//
// void Show()
// {
// std::cout << " Real and imaginary equation is " << r << " + " << i << "i " << std::endl << std::endl;
// }
// int getReal()
// {
// return r;
// }
// float getImagi()
// {
// return i;
// }
//
//};
//
//// ComplexNumber here is the return type like int getReal() and flot getImagi
//ComplexNumber AddBothObj(ComplexNumber obj1, ComplexNumber obj2)
//{
// int newR;
// float newI;
//
// newR = obj1.getReal() + obj2.getReal();
// newI = obj1.getImagi() + obj2.getImagi();
//
// ComplexNumber temp(newR, newI);
//
// return temp;
//}
//
//
//int main()
//{
// ComplexNumber comp1(3, 7), comp2(6, 14), comp3;
// comp1.Show();
// comp2.Show();
//
// comp3 = AddBothObj(comp1,comp2);
// comp3.Show();
//
// std::cin.get();
//}
AddBoth is a method of the class ComplexNumber that doesn't modify any instance member, neither m_r nor m_i. What it does is to add two complex numbers and return a new complex number. In the first block you call AddBoth and that call doesn't modify comp3, so you get a (0, 0) output because those happen to be the values to which the members of the instance are initialized to (see private section of the class). In the second block you assign the result of the sum to comp3 and then you print it. That's why you see the expected output.
As pointed out in the comments, in your example, comp3.AddBoth returns a temporary result and doesn't actually modify the current object itself. If you want that behavior you will have to do something like this:
void Add(ComplexNumber other) // you can also make other a const reference which would avoid unnecessary object copies (if the compiler doesn't optimize the copy away)
{
m_r = m_r + other.m_r; // or m_r += other.m_r
m_i = m_i + other.m_i; // or m_i += other.m_i
// if you want to you can also return a reference to the current object here if you
// wish to chain operations like comp3.Add(comp1).Add(comp2)
}
The usage would then be:
// assuming comp1, comp2 are instances of the ComplexNumber class
comp1.Add(comp2); // adds comp2 to comp1, result is "in" comp1
comp1.Show();
If you would rather want to create a new ComplexNumber object from the addition of two other ComplexNumbers you can do:
// notice the static keyword here meaning you don't call this function using an instance of ComplexNumber
static ComplexNumber AddBoth(ComplexNumber c1, ComplexNumber c2) // again you can make c1 and c2 const references
{
int re = c1.m_r + c2.m_r;
float img = c1.m_i + c2.m_i;
ComplexNumber temp(re, img);
return temp;
// or simply return ComplexNumber(c1.m_r + c2.m_r, c1.m_i + c2.m_i);
}
which you would then have to use like this:
// assuming comp1 and comp2 are instances of the ComplexNumber class
ComplexNumber comp3 = ComplexNumber::AddBoth(comp1, comp2); // add comp1 and comp2 and save the result in comp3
comp3.Show();
I think it is obvious that this is an exercise on classes and class objects in C++ but if you want to use complex numbers in real programs I would suggest you have a look at the std::complex data type provided by the C++ standard. I also don't see an obvious reason why the real and imaginary variables should be different data types (int and float).

How to find the closest point to the first point on the data file? C++

My data file looks like below:
x y z
0.068472 -0.024941 0.028884
.... .... ....
continued, there are more than 100 points.
I want to find the closest point among all the data points to point 1 (in
this case (0.068472,-0.024941, 0.028884). My code to read the file is below, what function should I add to find the closest point to point 1? Should I use the minimum function to find the minimum distance between point 1 and the other? But I am not sure how to write this in code.
// Program to read an input file
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
const int MAXI = 1000;
double x, y, z, xcoordinates[MAXI], ycoordinates[MAXI], zcoordinates[MAXI];
int i, count;
ifstream inFile("input-week6-ad-q4-2.txt"); // ifstream function to read the file
string line, c; // To read the characters
if (inFile.is_open()) {
getline(inFile, line); // To read the header of the input file then discard it
getline(inFile, line);
i = 0;
count = 0;
while (inFile >> x >> y >> z) {
xcoordinates[count] = x;
ycoordinates[count] = y;
zcoordinates[count] = z;
count = count + 1;
}
for (i = 0; i < count; i++) {
cout << xcoordinates[i] << " " << ycoordinates[i] << " " << zcoordinates[i] << "\n";
}
inFile.close();
} else {
cout << "The file could not be opened." << "\n"; // To check for any error
}
system("pause");
return 0;
}
The comments offer the right direction. If you are going to write your minimum distance finder is C++, you should start with a simple 2d point class and then derive a class to handle 3d points from that class by adding a 3rd coordinate. If you are simply going to use separate x, y, z coordinate and three separate arrays of double -- you might as well write the program in C.
Writing a base class for a 2d point isn't difficult at all. The only thing you need to be mindful of in order to then derive a 3d class from it is to declare your coordinate members as protected: so that all protected members of the 2d point class are available as protected member in the 3d class (class members are private by default and private members of the base are never accessible unless friended)
So what would a minimum 2d point base class look like? Well you would need x, y coordinates, you would need a default constructor to set x and y to 0.0 when the class is constructed, a constructor to takexandyvalues, and then a couple of accessor functions to get thexandy` values for use in your distance function.
A minimum 2d point class could be:
/* 2D Cartesian Coordinate Point */
class point2_t {
protected: /* allows derived class access to x, y when inherited */
double x, y; /* private members would not be accessible */
public:
point2_t () { x = 0.0, y = 0.0; } /* constructors */
point2_t (const double a, const double b) : x{a}, y{b} { }
const double& getx () const { return x; } /* access functions */
const double& gety () const { return y; }
double dist (const point2_t& p) { /* distance function */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()));
}
};
That will allow you to initialize a 2d point with values, get the values currently set and then calculate the distance from some other 2d point. While that will work great, it would still require reading the x and y values from the file and then creating a point by passing the coordinates to the constructor. (your could also write a setx(double x) and corresponding sety() to allow you to change the x, y values)
It would be really nice to be able to just cin >> point; and have it set the x, y values automatically and to be able to cout << point; to output the coordinates. You can do so by overloading the << and >> operators. That makes it really convenient to read and output the coordinate data. To do so you can add the following as member functions:
/* overload output and input operators */
friend std::ostream& operator << (std::ostream& os, const point2_t& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point2_t& p) {
is >> p.x >> p.y;
return is;
}
Once you have your 2d point class written, all you need to do is derive a 3d point class from it and add a z coordinate and the corresponding functions to handle all three coordinates instead of two. The basic form to derive a class from a base class including the protected members of the base class is:
class derived : public base {
/* additions */
};
A simple derivation from your 2d point class for a 3d point class (including the overloading << and >> operators) could be:
/* 3D Cartesian Coordinate Point derived from 2D point class */
class point_t: public point2_t {
protected:
double z; /* add z coordinate */
public:
point_t () { point2_t (0.0, 0.0); z = 0.0; }; /* default construct */
/* construct with initializer list */
point_t (const double a, const double b, const double c) :
point2_t (a, b), z{c} {}
const double& getz () const { return z; } /* add getz accessor */
double dist (const point_t& p) { /* extend distance */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()) +
(z-p.getz()) * (z-p.getz()));
}
/* extend operators */
friend std::ostream& operator << (std::ostream& os, const point_t& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point_t& p) {
is >> p.x >> p.y >> p.z;
return is;
}
};
Now you have a 3d point class that can calculate the distance between points. All that remains is creating an instance of the class for your 1st point, and a second temporary instance to read additional points from your file allowing you to compute the distance between the two. (a 3rd instance is handy if you want to save the coordinates for the closest point)
The only caveat with your data file is you need to discard the first line containing the x y z heading. While you can read a the line into a string with getline and simply ignore it, C++ also provides a stream function .ignore() which allows you to ignore up to the maximum number of readable characters until a delimiter is reached (the newline in this case). Simply include the limits header and you can then use:
std::ifstream f (argv[1]); /* open file stream */
...
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
(either way works)
There is no need to read all the points in the file into a container to process later just to find the minimum of the distance between the first point and the rest. All you need to do is store the first point (p1 below) and then compute the distance between it and the remaining points, saving the minimum distance (distmin below) found for each subsequent comparison. (you can also save the coordinate of the closest point if you like)
Putting that together in a short main() could look like:
int main (int argc, char **argv) {
if (argc < 2) { /* validate argument available for filename */
std::cerr << "error: insufficient input.\n";
return 1;
}
std::ifstream f (argv[1]); /* open file stream */
point_t p1, min, tmp; /* 1st, mininum & temporary points */
/* initialize minimum distance to maximum allowable */
double distmin = std::numeric_limits<double>::max();
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (!(f >> p1)) { /* read 1st point */
std::cerr << "error: failed read of p1\n";
return 1;
}
while (f >> tmp) { /* read remaining points */
double dist = tmp.dist (p1); /* get distance from p1 */
if (dist < distmin) { /* check less than distmin? */
distmin = dist; /* set new distmin */
min = tmp; /* set new closest point */
}
}
/* output results */
std::cout << "\nclosest point to " << p1 << "\n\n" << min <<
"\n\ndistance: " << distmin << '\n';
}
The complete example would then be:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
#include <limits>
/* 2D Cartesian Coordinate Point */
class point2_t {
protected: /* allows derived class access to x, y when inherited */
double x, y; /* private members would not be accessible */
public:
point2_t () { x = 0.0, y = 0.0; } /* constructors */
point2_t (const double a, const double b) : x{a}, y{b} { }
const double& getx () const { return x; } /* access functions */
const double& gety () const { return y; }
double dist (const point2_t& p) { /* distance function */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()));
}
/* overload output and input operators */
friend std::ostream& operator << (std::ostream& os, const point2_t& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point2_t& p) {
is >> p.x >> p.y;
return is;
}
};
/* 3D Cartesian Coordinate Point derived from 2D point class */
class point_t: public point2_t {
protected:
double z; /* add z coordinate */
public:
point_t () { point2_t (0.0, 0.0); z = 0.0; }; /* default construct */
/* construct with initializer list */
point_t (const double a, const double b, const double c) :
point2_t (a, b), z{c} {}
const double& getz () const { return z; } /* add getz accessor */
double dist (const point_t& p) { /* extend distance */
return sqrt ((x-p.getx()) * (x-p.getx()) +
(y-p.gety()) * (y-p.gety()) +
(z-p.getz()) * (z-p.getz()));
}
/* extend operators */
friend std::ostream& operator << (std::ostream& os, const point_t& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
friend std::istream& operator >> (std::istream& is, point_t& p) {
is >> p.x >> p.y >> p.z;
return is;
}
};
int main (int argc, char **argv) {
if (argc < 2) { /* validate argument available for filename */
std::cerr << "error: insufficient input.\n";
return 1;
}
std::ifstream f (argv[1]); /* open file stream */
point_t p1, min, tmp; /* 1st, mininum & temporary points */
/* initialize minimum distance to maximum allowable */
double distmin = std::numeric_limits<double>::max();
/* discard 1st line in file */
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (!(f >> p1)) { /* read 1st point */
std::cerr << "error: failed read of p1\n";
return 1;
}
while (f >> tmp) { /* read remaining points */
double dist = tmp.dist (p1); /* get distance from p1 */
if (dist < distmin) { /* check less than distmin? */
distmin = dist; /* set new distmin */
min = tmp; /* set new closest point */
}
}
/* output results */
std::cout << "\nclosest point to " << p1 << "\n\n" << min <<
"\n\ndistance: " << distmin << '\n';
}
Example Input File
Generating a few additional random points in the same range as your values would give you a data file with 10 total points to use to validate the program, e.g.
$ cat dat/3dpoints-10.txt
x y z
0.068472 -0.024941 0.028884
-0.023238 0.028574 -0.021372
0.015325 -0.086100 0.011980
-0.028137 -0.025350 0.021614
-0.013860 0.015710 -0.022659
0.026026 -0.093600 0.019175
0.010445 -0.098790 0.023332
-0.021594 0.017428 -0.025986
0.021800 -0.027678 0.017078
-0.016704 0.017951 0.011059
Example Use/Output
Running the program will then locate the closest point to your first point (p1) providing the following answer:
$ ./bin/point_distmin dat/3dpoints-10.txt
closest point to (0.068472, -0.024941, 0.028884)
(0.0218, -0.027678, 0.017078)
distance: 0.0482198
Look things over and let me know if you have questions. cpprefernce.com is one of the best references (aside from the standard itself). Keep that bookmark handy and take some time to get to know the language and the site.
This answer heavily builds on David C. Rankin's. The main() is pretty much copy-pasted with two extra checks, explicit stream closing and some style changes. The chief difference is the way points are stored and thus, treated. No inheritance here. And it's only POD struct anyway.
Data, data, data. You think about the task in terms of points, so you should have a datatype to neatly hold coordinates together as one point:
struct Point3d {
double x, y, z;
};
To cooperate fluently with C++ i/o streams, let's overload the >> and << operators:
std::ostream& operator << (std::ostream& os, const Point3d& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
std::istream& operator >> (std::istream& is, Point3d& p) {
is >> p.x >> p.y >> p.z;
return is;
}
Finally, we need to compute the distance between two points. Metrics are symmetric by logic and also by definition, so let us reflect it in code and define a simple function to compute Euclidean distance:
double distance(const Point3d &a, const Point3d &b) {
auto squared = std::pow(a.x-b.x, 2) +
std::pow(a.y-b.y, 2) +
std::pow(a.z-b.z, 2);
return sqrt(squared);
}
Then the whole program is:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
#include <limits>
struct Point3d {
double x, y, z;
};
std::ostream& operator << (std::ostream& os, const Point3d& p) {
os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
return os;
}
std::istream& operator >> (std::istream& is, Point3d& p) {
is >> p.x >> p.y >> p.z;
return is;
}
double distance(const Point3d &a, const Point3d &b) {
auto squared = std::pow(a.x-b.x, 2) +
std::pow(a.y-b.y, 2) +
std::pow(a.z-b.z, 2);
return sqrt(squared);
}
int main(int argc, char **argv) {
if (argc != 2) {
std::cerr << "Exactly one argument expected, got " << argc << "\n";
return 1;
}
std::ifstream f(argv[1]);
if (!f.is_open()) {
std::cerr << "error: failed to open '" << argv[1] << "'\n";
return 1;
}
// discard the header line
f.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Point3d first_pt;
if (!(f >> first_pt)) { // read the first point
std::cerr << "error: failed read of the first point\n";
return 1;
}
bool other_points = false;
double dist_min = std::numeric_limits<double>::max();
Point3d closest, current;
while (f >> current) { // loop through the other points
other_points = true;
double dist = distance(first_pt, current);
if (dist < dist_min) {
dist_min = dist;
closest = current;
}
}
f.close();
if (other_points) {
std::cout << "closest point to " << first_pt <<
" is " << closest << " [distance: " << dist_min << "]\n";
} else {
std::cout << "There was only one point in the file\n";
}
}
You can calculate the Euclidean distances of two points in 3 dimensions (point 1 vs the other points), then compare them to find the closest point. The formula could be found on Wiki: https://en.wikipedia.org/wiki/Euclidean_distance

C++ Function Overload / With objects

I made a class Valjak (Roller), and gave it variables h (height) and r (radius) and made functions for area (Oplosje) and volume (Volumen).
I created 2 objects and now I need to overload operator + in such way that result of adding two objects from class Valjak (roller) creates a new third object that has as height equal to the height of first object plus the height of second object, and radius that is the radius of first object plus radius of third object.
This is my code so far:
#include <iostream>
#include <math.h>
using namespace std;
class Valjak{
private: float r, h;
public:
Valjak(){
r = 1;
h = 1;
}
Valjak(float rr, float hh){
r = rr;
h = hh;
}
void Oplosje(){
cout << "Oplosje valjka je: " << 2 * (pow(r, 2)*3.14) + 2 * r*h << endl;
}
void Volumen(){
cout << "Volumen je: " << (pow(r, 2)*3.14) * h << endl;
}
};
int main(){
Valjak V1;
Valjak V2(5, 10);
cout << "Vrijednosti prvog objekta!" << endl;
V1.Oplosje();
V1.Volumen();
cout << "Vrijednosti drugog objekta" << endl;
V2.Oplosje();
V2.Volumen();
system("PAUSE");
return 0;
}
First, you must write getters for r and h, let's name them get_r and get_h:
class Valjak {
// ...
public:
float get_r() { return r; }
float get_h() { return h; }
// ...
}
Then overload operator + for two objects of Valjak class:
Valjak operator+(const Valjak & a, const Valjak & b)
{
return Valjak(a.get_r() + b.get_r(), a.get_h() + b.get_h());
}

C++ Operator and Conversion Issues

double mean(vector<Reading> temps)
{
// stub version
double mean_temp;
double sum = 0;
for (int i = 0; i< temps.size(); ++i) sum += temps[i];
mean_temp = sum/temps.size();
return (mean_temp);
}
double median(vector<Reading> temps)
{
// stub version
double median_temp;
sort (temps.begin(), temps.end());
median_temp = temps[temps.size()/2];
return (median_temp);
}
============================================
Result in errors:
proj4.cc: In function ‘double mean(Vector<Reading>)’:
proj4.cc:132: error: no match for ‘operator+=’ in ‘sum += temps.Vector<T>::operator[] [with T = Reading](((unsigned int)i))’
proj4.cc: In function ‘double median(Vector<Reading>)’:
proj4.cc:142: error: cannot convert ‘Reading’ to ‘double’ in assignment
=============================================
Full code below. I need to tackle these two errors before I can proceed
#include <bjarne/std_lib_facilities.h>
struct Reading {
int hour;
double temperature;
Reading(int h, double t): hour(h), temperature(t) { }
bool operator<(const Reading &r) const;
};
bool Reading::operator<(const Reading &r) const
{
// stub version
vector<Reading> temps;
sort (temps.begin(), temps.end());
}
/*
* function declarations
*/
ostream& operator<<(ostream& ost, const Reading &r);
vector<Reading> get_temps();
double check_adjust_temp(double temperature, char scale);
double c_to_f(double temperature);
double mean(vector<Reading> temps);
double median(vector<Reading> temps);
void print_results(const vector<Reading>& temps, double mean_temp,
double median_temp);
int main()
try
{
vector<Reading> temps = get_temps();
if (temps.size() == 0) error("no temperatures given!");
double mean_temp = mean(temps);
sort(temps.begin(), temps.end());
double median_temp = median(temps);
print_results(temps, mean_temp, median_temp);
}
catch (exception& e) {
cerr << "error: " << e.what() << '\n';
return 1;
}
catch (...) {
cerr << "Oops: unknown exception!\n";
return 2;
}
/*
* function definitions
*/
ostream& operator<<(ostream& ost, const Reading &r)
{
// stub version
/*
*/
return ost;
}
vector<Reading> get_temps()
{
// stub version
cout << "Please enter name of input file name: ";
string name;
cin >> name;
ifstream ist(name.c_str());
if(!ist) error("can't open input file ", name);
vector<Reading> temps;
int hour;
double temperature;
while (ist >> hour >> temperature){
if (hour <0 || 23 <hour) error("hour out of range");
temps.push_back( Reading(hour,temperature));
}
}
double check_adjust_temp(double temperature, char scale)
{
// stub version
if (scale== 'c' || 'C'){
return c_to_f(temperature);
}
else if (scale== 'f' || 'F') {
return temperature;
}
else {
error("Wrong input type");
}
}
double c_to_f(double temperature)
{
// stub version
double c;
c = ((temperature * (9.0/5)) + 32);
return (c);
}
double mean(vector<Reading> temps)
{
// stub version
double mean_temp;
double sum = 0;
for (int i = 0; i< temps.size(); ++i) sum += temps[i];
mean_temp = sum/temps.size();
return (mean_temp);
}
double median(vector<Reading> temps)
{
// stub version
double median_temp;
sort (temps.begin(), temps.end());
median_temp = temps[temps.size()/2];
return (median_temp);
}
void print_results(const vector<Reading>& temps, double mean_temp,
double median_temp)
{
// stub version
cout << "The sorted temperatures are:\n";
cout << get_temps;
cout << "The mean temperature is " << mean_temp << ".\n";
cout << "The median temperature is " << median_temp << ".\n";
}
Define a conversion operator for Reading:
struct Reading {
int hour;
double temperature;
Reading(int h, double t): hour(h), temperature(t) { }
bool operator<(const Reading &r) const;
operator double() { return temperature; }
};
Or, better (via the Principle of Least Astonishment), just change the usage of your class:
// was:
sum += temps[i];
//change to:
sum += temps[i].temperature;
// was:
median_temp = temps[temps.size()/2];
//change to:
median_temp = temps[temps.size()/2].temperature;
You're trying to execute an addition between an instance of a class Reading and a double. This doesn't work as long as you don't provide either a default conversion path from Reading to double:
Reading::operator double() const { return temperature; }
or by providing proper global operator+() overloads:
double operator+(Reading const&, double);
double operator+(double, Reading const&);
The second error should be solvable with the Reading::operator double() as shown above.
You are missing operator+= for the class Reading
you are trying to sum up Reading objects into a double variable!
sum += temps[i];
sum type is double while temps[i] returns Reading object, you cannot sum double and Reading object since they belong to different types, you must define an overload of plus operator and make the compiler understand how this is done.