C++ boost library cheat sheet
C++ boost library cheat sheet

C++ boost library cheat sheet

1. How to build the boost library

git clone https://github.com/boostorg/boost.git
cd boost
git submodule update --recursive --init

1.1. Build under MacOS X and Linux

./bootstrap.sh --prefix=./stage
./b2 -j4 cxxflags=-std=c++14

1.2. Build under Windows with Visual Studio 2017, 64 bit

call bootstrap.bat
b2 -j4 toolset=msvc-14.1 address-model=64 cxxflags=/std:c++14 define=BOOST_USE_WINAPI_VERSION=0x0601 define=_WIN32_WINNT=0x601

1.3. Build under Windows with MinGW, 32 bit

call bootstrap.bat
b2 -j4 toolset=gcc address-model=32 cxxflags=-std=c++14 define=BOOST_USE_WINAPI_VERSION=0x0601 define=_WIN32_WINNT=0x601

2. How to install the boost library (without building)

2.1. Debian

sudo apt-get install libboost-all-dev

2.2. MacOS X

brew install boost

The library will be installed to a versioned subfolder of /usr/local/Cellar/boost, e. g. /usr/local/Cellar/boost/1.70.0

2.3. Windows

Install the version matching your compiler from https://sourceforge.net/projects/boost/files/boost-binaries. The default location is a versioned subfolder at C:\local, e. g. C:\local\boost_1_70_0

3. Complex numbers

math_samples.hpp
#pragma once

void math_samples();
math_samples.cpp
#include "math_samples.hpp"

#include <iostream>
#include <complex>
#include <boost/rational.hpp>


void math_samples()
{
	std::complex<boost::rational<int>> a,b;

	boost::rational<int> pi(355, 113);
	std::cout << "Pi is approximately " << boost::rational_cast<double>(pi) << std::endl;

	using namespace std::complex_literals;
	std::cout << std::fixed << std::setprecision(1);

	std::complex<double> z1 = 1i * 1i;     // imaginary unit squared
	std::cout << "i * i = " << z1 << " = " << z1.real() << std::endl;

	std::complex<double> z2 = std::pow(1i, 2); // imaginary unit squared
	std::cout << "pow(i, 2) = " << z2 << " = " << z2.real() << std::endl;

	double PI = std::acos(-1);
	std::complex<double> z3 = std::exp(1i * PI); // Euler's formula
	std::cout << "e^(i * pi) = " << z3 << " = " << z3.real() << std::endl;

	std::complex<double> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
	std::cout << "(1+2i)*(1-2i) = " << z4*z5 << " = " << (z4*z5).real() << std::endl;
}

4. Parser

parser.hpp
#pragma once

#include <string>

// several ways how to use boost::spirit to parse a list of numbers like "3, 3.14, -2.5, 790" and a complex number like "(1.0, -4.0)"
void parser_sample(std::string numberList, std::string complexNumber);
parser.cpp
#include "parser.hpp"
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

void print(double const& val)
{
	std::cout << "Parsed number = " << val << std::endl;
}

template <typename Iterator>
bool parse_number_list(Iterator first, Iterator last)
{
	using boost::spirit::qi::double_;
	using boost::spirit::qi::rule;
	using boost::spirit::qi::phrase_parse;
	using boost::spirit::ascii::space;

	bool r = phrase_parse(
		first,                          /*< start iterator >*/
		last,                           /*< end iterator >*/
		double_[&print] >> *(',' >> double_[&print]),   /*< the parser >*/
		space                           /*< the skip-parser >*/
	);

	if (first != last) // fail if we did not get a full match
		return false;

	return r;
}

template <typename Iterator>
bool parse_four_numbers(Iterator first, Iterator last, double& a, double& b, double& c, double& d)
{
	using boost::spirit::qi::double_;
	using boost::spirit::qi::_1;
	using boost::spirit::qi::phrase_parse;
	using boost::spirit::ascii::space;
	using boost::phoenix::ref;

	bool r = phrase_parse(
		first,
		last,
		double_[ref(a) = _1] >> ',' >>
		double_[ref(b) = _1] >> ',' >>
		double_[ref(c) = _1] >> ',' >>
		double_[ref(d) = _1],
		space);

	if (!r || first != last) // fail if we did not get a full match
		return false;

	return r;
}

template <typename Iterator>
bool parse_numbers_into_vector(Iterator first, Iterator last, std::vector<double>& v)
{
	using boost::spirit::qi::double_;
	using boost::spirit::qi::phrase_parse;
	using boost::spirit::qi::_1;
	using boost::spirit::ascii::space;

	bool r = phrase_parse(
	first,
	last,
	double_ % ',',
	space,
	v);

	if (first != last) // fail if we did not get a full match
		return false;
	return r;
}

template <typename Iterator>
bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
{
	using boost::spirit::qi::double_;
	using boost::spirit::qi::_1;
	using boost::spirit::qi::phrase_parse;
	using boost::spirit::ascii::space;
	using boost::phoenix::ref;

	double rN = 0.0;
	double iN = 0.0;
	bool r = phrase_parse(first, last,

  //  Begin grammar
		(
			'(' >> double_[ref(rN) = _1]
			>> -(',' >> double_[ref(iN) = _1]) >> ')'
			|   double_[ref(rN) = _1]
		),
	  //  End grammar

	space);

	if (!r || first != last) // fail if we did not get a full match
		return false;
	c = std::complex<double>(rN, iN);
	return r;
}

void parser_sample(std::string numberList, std::string complexNumber)
{
	if (parse_number_list(numberList.begin(), numberList.end()))
	{
		std::cout << "Parsing number list succeeded" << std::endl;
	}
	else
	{
		std::cout << "Parsing number list failed" << std::endl;
	}

	double a, b, c, d;
	if (parse_four_numbers(numberList.begin(), numberList.end(), a, b, c, d))
	{
		std::cout << "Parsing 4 numbers succeeded: " << a << " " << b << " " << c << " " << d << std::endl;
	}
	else
	{
		std::cout << "Parsing 4 numbers failed" << std::endl;
	}

	std::vector<double> result;
	if (parse_numbers_into_vector(numberList.begin(), numberList.end(), result))
	{
		std::cout << "Parsing numbers into std::vector succeeded: ";
		for (double& val : result) std::cout << val << " ";
		std::cout << std::endl;
	}
	else
	{
		std::cout << "Parsing  numbers into std::vector failed" << std::endl;
	}

	std::complex<double> cpl;
	if (parse_complex(complexNumber.begin(), complexNumber.end(), cpl))
	{
		std::cout << "Parsed complex number " << cpl << std::endl;
	}
	else
	{
		std::cout << "Parsing complex number failed." << std::endl;
	}
}

5. Sockets

socket.hpp
#pragma once

#include<string>

bool send_to_socket(std::string address, int port, std::string content);
socket.cpp
#include "socket.hpp"

#ifdef _WIN32
	#define _WIN32_WINNT 0x0601 //_WIN32_WINNT_WIN7
#endif

#include <boost/asio.hpp>


bool send_to_socket(std::string address, int port, std::string content)
{
	boost::asio::io_service io_service;
	boost::asio::ip::tcp::socket socket(io_service);
  connect(socket, boost::asio::ip::tcp::resolver(io_service).resolve({address, std::to_string(port)}));

	return write(socket, boost::asio::buffer(content)) == content.length();
}

6. Read and write XML

demo.xml
<?xml version="1.0" encoding="UTF-8"?>
<SZSamples>
    <title>sample xml file</title>
    <version>1</version>
    <point>
        <x>10.38</x>
        <y>1.81</y>
    </point>
    <point>
        <x>5.45</x>
        <y>-3.68</y>
    </point>
    <point>
        <x>5.89</x>
        <y>5.49</y>
    </point>
</SZSamples>
xml.hpp
#pragma once

#include <string>
#include <vector>

// read and write an xml file containing a title, a version and a list of x/y coordinates

void         read_xml(std::string filename, std::string& title, int& version, std::vector<std::pair<double, double>>& coordList);
void write_properties(std::string filename, std::string  title, int  version, std::vector<std::pair<double, double>>  coordList);
xml.cpp
#include "xml.hpp"

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

// includes to write additional formats info and json
#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/json_parser.hpp>

void  read_xml(std::string filename, std::string& title, int& version, std::vector<std::pair<double, double>>& coordList)
{
	boost::property_tree::ptree tree;
	boost::property_tree::xml_parser::read_xml(filename, tree);

	title   = tree.get<std::string>("SZSamples.title");
	version = tree.get<int>("SZSamples.version");

	for (boost::property_tree::ptree::value_type& v : tree.get_child("SZSamples"))
	{
		if (v.first == "point")
		{
			double x = v.second.get<double>("x");
			double y = v.second.get<double>("y");

			coordList.emplace_back(std::make_pair(x, y));
		}
	}
}

void write_properties(std::string filename, std::string  title, int  version, std::vector<std::pair<double, double>> coordList)
{
	boost::property_tree::ptree tree;

	tree.put("SZSamples.title", title);
	tree.put("SZSamples.version", version);

	for (auto coord : coordList)
	{
		boost::property_tree::ptree point;
		point.add("x", coord.first);
		point.add("y", coord.second);

		tree.add_child("SZSamples.point", point);
	}

	boost::property_tree::write_xml(filename+".xml", tree);
	boost::property_tree::write_info(filename+".ini", tree);
	boost::property_tree::write_json(filename+".json", tree);
}