Blog: Articles on C++11 and Computational Finance (by Daniel J. Duffy)

Daniel Duffy

C++ author, trainer
Code:
// TestSTLVariant101.cpp
//
// Show the essentials of the Variant Library in Boost.
// Supported in C++17, std::variant and std::visit()
//
// Show a variety of methods for type-safe visitation of type-safe unions.
//
// Q. can you get std::variant working with boost::static_visitor<>?
//
// BIG DEAL is: adding functionality NON-INTRUSIVELY to a class by Visior pattern.
//
// (C) Datasim Education BV 2009-2019
//

#include <iostream>
#include <boost/variant.hpp>
#include <variant>

// Basic shapes
struct Point
{
    double x;
    double y;

    void displayPoint()
    {
        std::cout << "Point: " << x << ", " << y << '\n';
    }
};

struct Circle
{
    Point centre;
    double radius;

    void displayCircle()
    {
        std::cout << "Circle, radius " << radius  << '\n';
        std::cout << "Centre point "; centre.displayPoint();
    }

};

struct LineSegment
{
    Point p1;
    Point p2;

    void displayLineSegment()
    {
        std::cout << "Line, endpoints "<< '\n';
        p1.displayPoint();
        p2.displayPoint();
    }
};

using VariantBoost = boost::variant<Point, LineSegment, Circle>;
using VariantSTL = std::variant<Point, LineSegment, Circle>;

// Different ways to add functionality/visit shapes

// A. In combination with Boost visitor pattern
class Print_Visitor : public boost::static_visitor<void>
{
public:
    void operator () (Point& s) { s.displayPoint(); }
    void operator () (LineSegment& s) { s.displayLineSegment(); }
    void operator () (Circle& s) { s.displayCircle(); }
};

class Translate_Visitor : public boost::static_visitor<void>
{ // Move the shapes

private:
    double off;

public:
    Translate_Visitor(double offset) : off(offset) {}
    void operator () (Point& s) { s.x += off; s.y += off;}
    void operator () (LineSegment& s) {(*this)(s.p1); (*this)(s.p2);}
    void operator () (Circle& s) { (*this)(s.centre); }
};

// B. Lambda function to test each type
auto lambdaVisit = [](auto&& arg)
{
    using T = std::decay_t < decltype(arg)>;

    // Hard-coded switch
    if constexpr (std::is_same_v<T, Point>)
        arg.displayPoint();

    if constexpr (std::is_same_v<T, LineSegment>)
        arg.displayLineSegment();

    if constexpr (std::is_same_v<T, Circle>)
        arg.displayCircle();
};

void MyVisit(VariantSTL& var)
{
    std::visit(lambdaVisit, var);
}



void MyVisit2(VariantSTL& v)
{
    switch (v.index()) {
    case 0:
        std::get<0>(v).displayPoint();
        break;
    case 1:
        std::get<1>(v).displayLineSegment();
        break;
    case 2:
        std::get<2>(v).displayCircle();
        break;
    default:
        std::cout << "ugh\n";
    }
}

void MyVisit3(VariantSTL& v)
{

    switch (v.index()) {
    case 0:
        std::get<Point>(v).displayPoint();
        break;
    case 1:
        std::get<LineSegment>(v).displayLineSegment();
        break;
    case 2:
        std::get<Circle>(v).displayCircle();
        break;
    default:
        std::cout << "ugh\n";
    }
}
int main()
{
    // Create some shapes
    Point p1{ 1,1 };
    Point p2{ 2,1 };
    LineSegment myL{ p1, p2 };
    double radius = 2.0;
    Circle c{ p1, radius };

    // Checking the data
    std::cout << "\n*** Sanity checks \n";
    p1.displayPoint(); p2.displayPoint();
    myL.displayLineSegment(); c.displayCircle();

    {

        // Boost Visitor
        std::cout << "\n*** C++11 visit using Boost visitor \n";
        VariantBoost var(p1);
        Print_Visitor vis;

        // Give some values; visit each component
        var = p1;
        boost::apply_visitor(vis, var);

        var = myL;
        boost::apply_visitor(vis, var);

        var = c;
        boost::apply_visitor(vis, var);
    }

    // C++11 solution
    {
        std::cout << "\n*** C++11 visit\n";
        VariantSTL var(p1);
        MyVisit(var);

        var = c;
        MyVisit(var);

        var = myL;
        MyVisit(var);

    }
  
    // C. Based on the variant's index
    {
        std::cout << "\n*** C++11 visit using indices \n";
        VariantSTL var(p1);
        MyVisit2(var);

        var = c;
        MyVisit2(var);

        var = myL;
        MyVisit2(var);

    }
    // D. Based on the variant's type
    {
        std::cout << "\n*** C++11 visit using type as index \n";
        VariantSTL var(p1);
        MyVisit3(var);

        var = c;
        MyVisit3(var);

        var = myL;
        MyVisit3(var);

    }

    // E. Translate Visitor
    {
        std::cout << "\n*** Translate visitor \n";
      
        Point p{ 0.0, 0.0 };
        Point p2 {1.0, 1.0 };
        LineSegment myL{ p, p2 };
        Circle c{ p, 10.0 };

        // Boost Visitor
        std::cout << "\n*** C++11 visit using Boost visitor \n";
        VariantBoost var(p);

        double offset = 2.0;
        Translate_Visitor vis(offset);
        Print_Visitor visP;

        // Give some values; visit each component
        var = p;
        boost::apply_visitor(vis, var);
        boost::apply_visitor(visP, var);

        var = myL;
        boost::apply_visitor(vis, var);
        boost::apply_visitor(visP, var);

        var = c;
        boost::apply_visitor(vis, var);
        boost::apply_visitor(visP, var);

    /*    p.displayPoint();
        myL.displayLineSegment();
        c.displayCircle();*/


    }

     return 0;
}
C++17 (and Boost) type-safe variant and its visitors. Use /std:c++latest
 

Attachments

Daniel Duffy

C++ author, trainer
Some weekend thoughts ...
I didn't always work on high-level languages like C++. Once upon a time I was a summer intern with GE in Ireland testing diodes and triodes (big ones!) using Basic on a noisy teletype machine connected to the computer in Scotland by a very long cable.

Advantage of paper tape: no chance of hacking, easy to make backup
Disadvantage code difficult to maintain (need a pair of scissors .. cut and paste). And earplugs. These days people never had it so good :unsure: 😂

29781
29782
 
Last edited:

Daniel Duffy

C++ author, trainer
C++ 2020 Concepts, finally

Concepts are an extension to the templates feature provided by the C++ programming language.[...] concepts are named Boolean predicates on template parameters, evaluated at compile time. A concept may be associated with a template (class template, function template, or member function of a class template), in which case it serves as a constraint: it limits the set of arguments that are accepted as template parameters.

C++20 Concepts Are Here in Visual Studio 2019 version 16.3 – C++ Team Blog

 

Daniel Duffy

C++ author, trainer
Boost C++ Histogram library.



This library provides a histogram for multi-dimensional data. In the multi-dimensional case, the input consist of tuples of values which belong together and describing different aspects of the same entity. For example, when you make a digital image with a camera, photons hit a pixel detector. The photon is the entity and it has two coordinates values where it hit the detector. The camera only counts how often a photon hit each cell, so it is a real-life example of making a two-dimensional histogram. A two-dimensional histogram collects more information than two separate one-dimensional histograms, one for each coordinate. For example, if the two-dimensional image looks like a checker board, with high and low densities are alternating along each coordinate, then the one-dimensional histograms along each coordinate would look flat. There would be no hint that there is a complex structure in two dimensions.
 

Daniel Duffy

C++ author, trainer
They don't write well-researched books like this any more.

R.G. Dromey How to Solve it by Computer Prentice-Hall 1982

It discusses how to write well-structured modular programs and deep discussions of algorithms and data structures and code in Pascal.
For example, this is a good front-end to C++ STL algorithms and data structures.

Most books (e.g. in Python) are

30% screen sheets
40% tables of output
20% text
10% maths (if you are lucky)

Very little background (e.g. maths, fianance) and certainly no help in developing your own algorithms.

Just using libraries and packages alone means you will always us libraries and packages at the cost of real software design skill IMHO.

BTW I have stopped buying books on Python, for the above reasons.

Caveat: "each to his own"
 
Last edited:
Top