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 <format>
#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::format("{:12} : ({:8}, {:8}))", p.name, p.a, p.e);
return os;
}
int main() {
std::vector<Planet> planets{{.name="Mercury", .a=0.3871, .e=0.2056},
{.name="Venus", .a=0.7233, .e=0.0068},
{.name="Earth", .a=1.0000, .e=0.0167},
{.name="Mars", .a=1.5237, .e=0.0934},
{.name="Jupiter", .a=5.2029, .e=0.0484},
{.name="Saturn", .a=9.5370, .e=0.0539},
{.name="Uranus", .a=19.189, .e=0.0473},
{.name="Neptune", .a=30.070, .e=0.0086}};
std::sort(planets.begin(), planets.end(),
[] (const Planet& a, const Planet& b) {return a.e < b.e;});
for (const auto& p : planets) {
std::cout << p << std::endl;
}
}