Example: Sorting Planets
Let’s use our new understanding of lambda functions to enable std::sort()
to sort our planets vector based on eccentricity.
And, let’s add one more trick—we’ll create a function that tells C++
how to output our Planet
object directly.
Recall, that our Planet
is a struct
of the form:
struct Planet
{
std::string name{};
double a{}; // semi-major axis
double e{}; // eccentricity
};
We’d like to be able to do:
Planet p;
...
std::cout << p << std::endl;
We need to write a function that takes an output stream (std::ostream
)
and returns a reference to that same output stream.
Here’s how this function looks:
std::ostream& operator<< (std::ostream& os, const Planet& p) {
os << std::setw(12) << p.name << " : ("
<< std::setw(8) << p.a << " , "
<< std::setw(8) << p.e << ")";
return os;
}
Note
Previously we saw that we could not write a function that returns a
reference to a local object. But here, the return value, os
, is
not local—we pass a reference to it via the argument list.
This construction is what allows us to string <<
together.
Here’s the full code of initializing our planets, sorting by eccentricity, and then outputting them.
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
struct Planet
{
std::string name{};
double a{}; // semi-major axis
double e{}; // eccentricity
};
std::ostream& operator<< (std::ostream& os, const Planet& p) {
os << std::setw(12) << p.name << " : ("
<< std::setw(8) << p.a << " , "
<< std::setw(8) << p.e << ")";
return os;
}
int main() {
std::vector<Planet> planets {{"Mercury", 0.3871, 0.2056},
{"Venus", 0.7233, 0.0068},
{"Earth", 1.0000, 0.0167},
{"Mars", 1.5237, 0.0934},
{"Jupiter", 5.2029, 0.0484},
{"Saturn", 9.5370, 0.0539},
{"Uranus", 19.189, 0.0473},
{"Neptune", 30.070, 0.0086}};
std::sort(planets.begin(), planets.end(),
[] (const Planet& a, const Planet& b) {return a.e < b.e;});
for (auto p : planets) {
std::cout << p << std::endl;
}
}