Example: Sorting Planets

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.

Listing 58 planet_sort.cpp#
#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;
    }

}