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

}