Boost C++ Application Development Cookbook

4.5 (2 reviews total)
By Antony Polukhin
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Starting to Write Your Application

About this book

Boost libraries are developed by professionals, tested on multiple platforms and processor architectures, and contain reliable solutions for a wide range of tasks. This Cookbook takes you on a journey of simplifying the process of application development and guides you through writing perfect applications fast.

"Boost C++ Application Development Cookbook" provides you with a number of clear step-by-step recipes that will help you take advantage of the real power of Boost and C++, while giving you a good grounding in using it in any project.

"Boost C++ Application Development Cookbook" looks at the Boost libraries, and breaks down the mystery and confusion about which library to use in which situation. It will take you through a number of clear, practical recipes that will help you to take advantage of the readily available solutions.

Boost C++ Application Development Cookbook starts with teaching the basics of Boost libraries that are now mostly part of C++11 and leave no chance for memory leaks. Managing resources will become a piece of cake. We’ll see what kind of work can be done at compile time and what Boost containers can do. Do you think multithreading is a burden? Not with Boost. Think writing portable and fast servers is impossible? You’ll be surprised! Compilers and operating systems differ too much? Not with Boost. From manipulating images to graphs, directories, timers, files, strings – everyone will find an interesting topic.

You will learn everything for the development of high quality fast and portable applications. Write a program once and then you can use it on Linux, Windows, MacOS, Android operating systems.

Publication date:
August 2013
Publisher
Packt
Pages
348
ISBN
9781849514880

 

Chapter 1. Starting to Write Your Application

In this chapter we will cover:

  • Getting configuration options

  • Storing any value in a container/variable

  • Storing multiple chosen types in a container/variable

  • Using a safer way to work with a container that stores multiple chosen types

  • Returning a value or flag where there is no value

  • Returning an array from a function

  • Combining multiple values into one

  • Reordering the parameters of a function

  • Binding a value as a function parameter

  • Using the C++11 move emulation

  • Making a noncopyable class

  • Making a noncopyable but movable class

 

Introduction


Boost is a collection of C++ libraries. Each library has been reviewed by many professional programmers before being accepted to Boost. Libraries are tested on multiple platforms using many compilers and the C++ standard library implementations. While using Boost, you can be sure that you are using one of the most portable, fast, and reliable solutions that is distributed under a license suitable for commercial and open source projects.

Many parts of Boost have been included in C++11, and even more parts are going to be included in the next standard of C++. You will find C++11-specific notes in each recipe of this book.

Without a long introduction, let's get started!

In this chapter we will see some recipes for everyday use. We'll see how to get configuration options from different sources and what can be cooked up using some of the datatypes introduced by Boost library authors.

 

Getting configuration options


Take a look at some of the console programs, such as cp in Linux. They all have a fancy help, their input parameters do not depend on any position, and have a human readable syntax, for example:

$ cp --help 

Usage: cp [OPTION]... [-T] SOURCE DEST 
  -a, --archive           same as -dR --preserve=all 
  -b                      like --backup but does not accept an argument

You can implement the same functionality for your program in 10 minutes. And all you need is the Boost.ProgramOptions library.

Getting ready

Basic knowledge of C++ is all you need for this recipe. Remember that this library is not a header-only, so your program will need to link against the libboost_program_options library.

How to do it...

Let's start with a simple program that accepts the number of apples and oranges as input and counts the total number of fruits. We want to achieve the following result:

$ our_program –apples=10 –oranges=20
Fruits count: 30

Perform the following steps:

  1. First of all, we need to include the program_options header and make an alias for the boost::program_options namespace (it is too long to type it!). We would also need an <iostream> header:

    #include <boost/program_options.hpp>
    #include <iostream>
    namespace opt = boost::program_options;
  2. Now we are ready to describe our options:

    // Constructing an options describing variable and giving
    // it a textual description "All options" to it.
    opt::options_description desc("All options");
        
    // When we are adding options, first parameter is a name
    // to be used in command line. Second parameter is a type
    // of that option, wrapped in value<> class. 
    // Third parameter must be a short description of that 
    // option
    desc.add_options()
        ("apples", opt::value<int>(), "how many apples do you have")
        ("oranges", opt::value<int>(), "how many oranges do you have")
    ;
  3. We'll see how to use a third parameter a little bit later, after which we'll deal with parsing the command line and outputting the result:

    // Variable to store our command line arguments
    opt::variables_map vm;
        
    // Parsing and storing arguments
    opt::store(opt::parse_command_line(argc, argv, desc), vm);
    opt::notify(vm);
    std::cout << "Fruits count: "
        << vm["apples"].as<int>() + vm["oranges"].as<int>()
        << std::endl;

    That was simple, wasn't it?

  4. Let's add the --help parameter to our option's description:

        ("help", "produce help message")
  5. Now add the following lines after opt::notify(vm);, and you'll get a fully functional help for your program:

    if (vm.count("help")) {
        std::cout << desc << "\n";
        return 1;
    }

    Now, if we call our program with the --help parameter, we'll get the following output:

    All options: 
      --apples arg          how many apples do you have 
      --oranges arg         how many oranges do you have 
      --help                produce help message

    As you can see, we do not provide a type for the option's value, because we do not expect any values to be passed to it.

  6. Once we have got through all the basics, let's add short names for some of the options, set the default value for apples, add some string input, and get the missing options from the configuration file:

    #include <boost/program_options.hpp>
    // 'reading_file' exception class is declared in errors.hpp
    #include <boost/program_options/errors.hpp>
    #include <iostream>
    namespace opt = boost::program_options;
    
    int main(int argc, char *argv[])
    {
        opt::options_description desc("All options");
        // 'a' and 'o' are short option names for apples and 
        // oranges 'name' option is not marked with 
        // 'required()', so user may not support it
        desc.add_options()
            ("apples,a", opt::value<int>()->default_value(10), "apples that you have")
            ("oranges,o", opt::value<int>(), "oranges that you have")
            ("name", opt::value<std::string>(), "your name")
            ("help", "produce help message")
        ;
        opt::variables_map vm;
     // Parsing command line options and storing values to 'vm'
     
       opt::store(opt::parse_command_line(argc, argv, desc), vm);
        // We can also parse environment variables using 
        // 'parse_environment' method
        opt::notify(vm);
        if (vm.count("help")) {
            std::cout << desc << "\n";
            return 1;
        }
        // Adding missing options from "aples_oranges.cfg" 
        // config file.
        // You can also provide an istreamable object as a 
        // first parameter for 'parse_config_file'
        // 'char' template parameter will be passed to
        // underlying std::basic_istream object
        try {
          opt::store(
            opt::parse_config_file<char>("apples_oranges.cfg", desc), 
            vm
          );
        } catch (const opt::reading_file& e) {
            std::cout 
               << "Failed to open file 'apples_oranges.cfg': "
               << e.what();
        }
        opt::notify(vm);
        if (vm.count("name")) {
          std::cout << "Hi," << vm["name"].as<std::string>() << "!\n";
        }
    
        std::cout << "Fruits count: "
            << vm["apples"].as<int>() + vm["oranges"].as<int>()
            << std::endl;
        return 0;
    }

    Note

    When using a configuration file, we need to remember that its syntax differs from the command-line syntax. We do not need to place minuses before the options. So our apples_oranges.cfg option must look like this:

    oranges=20

How it works...

This example is pretty trivial to understand from code and comments. Much more interesting is what output we get on execution:

$ ./our_program --help 
All options: 
  -a [ --apples ] arg (=10) how many apples do you have 
  -o [ --oranges ] arg      how many oranges do you have 
  --name arg                your name 
  --help                    produce help message 

$ ./our_program 
Fruits count: 30

$ ./our_program -a 10 -o 10 --name="Reader" 
Hi,Reader! 
Fruits count: 20

There's more...

The C++11 standard adopted many Boost libraries; however, you won't find Boost.ProgramOptions in it.

See also

Tip

Downloading the example code

You can download the example code files for all Packt books that you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.

 

Storing any value in a container/variable


If you have been programming in Java, C#, or Delphi, you will definitely miss the ability to create containers with the Object value type in C++. The Object class in those languages is a basic class for almost all types, so you are able to assign (almost) any value to it at any time. Just imagine how great it would be to have such a feature in C++:

#include <iostream>
#include <vector>
#include <string>
#include <auto_ptr.h>

int main()
{
    typedef std::auto_ptr<Object> object_ptr;
    std::vector<object_ptr> some_values;
    some_values.push_back(new Object(10));
    some_values.push_back(new Object("Hello there"));
    some_values.push_back(new Object(std::string("Wow!")));
    std::string* p = 
         dynamic_cast<std::string*>(some_values.back().get());
    assert(p);

    (*p) += " That is great!\n";
    std::cout << *p;
    return 0;
}

Getting ready

We'll be working with the header-only library. Basic knowledge of C++ is all you need for this recipe.

How to do it...

In such cases, Boost offers a solution, the Boost.Any library, which has an even better syntax:

#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<boost::any> some_values;
    some_values.push_back(10);
    const char* c_str = "Hello there!";
    some_values.push_back(c_str);
    some_values.push_back(std::string("Wow!"));
    std::string& s = 
       boost::any_cast<std::string&>(some_values.back());
    s += " That is great!\n";
    std::cout << s;
    return 0;
}

Great, isn't it? By the way, it has an empty state, which could be checked using the empty() member function (just as in STL containers).

You can get the value from boost::any using two approaches:

    boost::any variable(std::string("Hello world!"));

    //#1: Following method may throw a boost::bad_any_cast exception
    // if actual value in variable is not a std::string
    std::string s1 = boost::any_cast<std::string>(variable);

    //#2: If actual value in variable is not a std::string
    // will return an NULL pointer
    std::string* s2 = boost::any_cast<std::string>(&variable);

How it works...

The boost::any class just stores any value in it. To achieve this it uses the type erasure technique (close to what Java or C# does with all of its types). To use this library, you do not really need to know its internal implementation, so let's just have a quick glance at the type erasure technique. Boost.Any, on assignment of some variable of type T, constructs a type (let's call it holder<T>) that may store a value of the specified type T, and is derived from some internal base-type placeholder. A placeholder has virtual functions for getting std::type_info of a stored type and for cloning a stored type. When any_cast<T>() is used, boost::any checks that std::type_info of a stored value is equal to typeid(T) (the overloaded placeholder's function is used for getting std::type_info).

There's more...

Such flexibility never comes without a cost. Copy constructing, value constructing, copy assigning, and assigning values to instances of boost::any will call a dynamic memory allocation function; all of the type casts need to get runtime type information (RTTI); boost::any uses virtual functions a lot. If you are keen on performance, see the next recipe, which will give you an idea of how to achieve almost the same results without dynamic allocations and RTTI usage.

Another disadvantage of Boost.Any is that it cannot be used with RTTI disabled. There is a possibility to make this library usable even with RTTI disabled, but it is not currently implemented.

Note

Almost all exceptions in Boost derive from the std::exception class or from its derivatives, for example, boost::bad_any_cast is derived from std::bad_cast. It means that you can catch almost all Boost exceptions using catch (const std::exception& e).

See also

 

Storing multiple chosen types in a variable/container


Are you aware of the concept of unrestricted unions in C++11? Let me tell you about it in short. C++03 unions can only hold extremely simple types of data called POD (plain old data). So in C++03, you cannot, for example, store std::string or std::vector in a union. C++11 relaxes this requirement, but you'll have to manage the construction and destruction of such types by yourself, call in-place construction/destruction, and remember what type is stored in a union. A huge amount of work, isn't it?

Getting ready

We'll be working with the header-only library, which is simple to use. Basic knowledge of C++ is all you need for this recipe.

How to do it...

Let me introduce the Boost.Variant library to you.

  1. The Boost.Variant library can store any of the types specified at compile time; it also manages in-place construction/destruction and doesn't even require the C++11 standard:

    #include <boost/variant.hpp>
    #include <iostream>
    #include <vector>
    #include <string>
    
    int main()
    {
        typedef boost::variant<int, const char*, std::string> 
          my_var_t;
        std::vector<my_var_t> some_values;
        some_values.push_back(10);
        some_values.push_back("Hello there!");
        some_values.push_back(std::string("Wow!"));
        std::string& s = boost::get<std::string>(some_values.back());
        s += " That is great!\n";
        std::cout << s;
        return 0;
    }

    Great, isn't it?

  2. Boost.Variant has no empty state, but has an empty() function, which always returns false. If you do need to represent an empty state, just add some trivial type at the first position of the types supported by the Boost.Variant library. When Boost.Variant contains that type, interpret it as an empty state. Here is an example in which we will use a boost::blank type to represent an empty state:

        typedef boost::variant<boost::blank, int, const char*, std::string> my_var_t;
        // Default constructor will construct an 
        // instance of boost::blank
        my_var_t var;
        // 'which()' method returns an index of a type,
        // currently held by variant.
        assert(var.which() == 0); // Empty state
        var = "Hello, dear reader";
        assert(var.which() != 0);
  3. You can get a value from a variant using two approaches:

        boost::variant<int, std::string> variable(0);
        // Following method may throw a boost::bad_get
        // exception if actual value in variable is not an int
        int s1 = boost::get<int>(variable);
        // If actual value in variable is not an int
        // will return an NULL pointer
        int* s2 = boost::get<int>(&variable);

How it works...

The boost::variant class holds an array of characters and stores values in that array. Size of the array is determined at compile time using sizeof() and functions to get alignment. On assignment or construction of boost::variant, the previous values are in-place destroyed, and new values are constructed on top of the character array using the new placement.

There's more...

The Boost.Variant variables usually do not allocate memory in a heap, and they do not require RTTI to be enabled. Boost.Variant is extremely fast and used widely by other Boost libraries. To achieve maximum performance, make sure that there is a trivial type in the list of supported types, and that this type is at the first position.

Note

Boost.Variant is not a part of the C++11 standard.

See also

 

Using a safer way to work with a container that stores multiple chosen types


Imagine that you are creating a wrapper around some SQL database interface. You decided that boost::any will perfectly match the requirements for a single cell of the database table. Some other programmer will be using your classes, and his task would be to get a row from the database and count the sum of the arithmetic types in a row.

Here's how the code would look:

#include <boost/any.hpp>
#include <vector>
#include <string>
#include <typeinfo>
#include <algorithm>
#include <iostream>

// This typedefs and methods will be in our header,
// that wraps around native SQL interface
typedef boost::any cell_t;
typedef std::vector<cell_t> db_row_t;

// This is just an example, no actual work with database.
db_row_t get_row(const char* /*query*/) {
    // In real application 'query' parameter shall have a 'const
    // char*' or 'const std::string&' type? See recipe Using a 
    // reference to string type in Chapter 7, Manipulating Strings
    // for an answer.
    db_row_t row;
    row.push_back(10);
    row.push_back(10.1f);
    row.push_back(std::string("hello again"));
    return row;
}

// This is how a user will use your classes
struct db_sum: public std::unary_function<boost::any, void> {
private:
    double& sum_;
public:
    explicit db_sum(double& sum)
        : sum_(sum)
    {}

    void operator()(const cell_t& value) {
        const std::type_info& ti = value.type();
        if (ti == typeid(int)) {
            sum_ += boost::any_cast<int>(value);
        } else if (ti == typeid(float)) {
            sum_ += boost::any_cast<float>(value);
        }
    }
};

int main()
{
    db_row_t row = get_row("Query: Give me some row, please.");
    double res = 0.0;
    std::for_each(row.begin(), row.end(), db_sum(res));
    std::cout << "Sum of arithmetic types in database row is: " << res << std::endl;
    return 0;
}

If you compile and run this example, it will output a correct answer:

Sum of arithmetic types in database row is: 20.1

Do you remember what your thoughts were when reading the implementation of operator()? I guess they were, "And what about double, long, short, unsigned, and other types?". The same thoughts will come to the mind of a programmer who will use your interface. So you'll need to carefully document values stored by your cell_t, or read the more elegant solution described in the following sections.

Getting ready

Reading the previous two recipes is highly recommended if you are not already familiar with the Boost.Variant and Boost.Any libraries.

How to do it...

The Boost.Variant library implements a visitor programming pattern for accessing the stored data, which is much safer than getting values via boost::get<>. This pattern forces the programmer to take care of each variant type, otherwise the code will fail to compile. You can use this pattern via the boost::apply_visitor function, which takes a visitor functional object as the first parameter and a variant as the second parameter. Visitor functional objects must derive from the boost::static_visitor<T> class, where T is a type being returned by a visitor. A visitor object must have overloads of operator() for each type stored by a variant.

Let's change the cell_t type to boost::variant<int, float, string> and modify our example:

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

// This typedefs and methods will be in header,
// that wraps around native SQL interface.
typedef boost::variant<int, float, std::string> cell_t;
typedef std::vector<cell_t> db_row_t;

// This is just an example, no actual work with database.
db_row_t get_row(const char* /*query*/) {
    // See the recipe "Using a reference to string type" 
    // in Chapter 7, Manipulating Strings
    // for a better type for 'query' parameter.
    db_row_t row;
    row.push_back(10);
    row.push_back(10.1f);
    row.push_back("hello again");
    return row;
}

// This is how code required to sum values
// We can provide no template parameter
// to boost::static_visitor<> if our visitor returns nothing.
struct db_sum_visitor: public boost::static_visitor<double> {
    double operator()(int value) const {
        return value;
    }
    double operator()(float value) const {
        return value;
    }
    double operator()(const std::string& /*value*/) const {
        return 0.0;
    }
};

int main()
{
    db_row_t row = get_row("Query: Give me some row, please.");
    double res = 0.0;
    db_row_t::const_iterator it = row.begin(), end = row.end();
    for (; it != end; ++it) {
         res += boost::apply_visitor(db_sum_visitor(), *it);
    }
    std::cout << "Sum of arithmetic types in database row is: " << res << std::endl;
    return 0;
}

How it works...

The Boost.Variant library will generate a big switch statement at compile time, each case of which will call a visitor for a single type from the variant's list of types. At runtime, the index of the stored type can be retrieved using which(), and a jump to the correct case in the switch will be made. Something like this will be generated for boost::variant<int, float, std::string>:

switch (which())
{
case 0: return visitor(*reinterpret_cast<int*>(address()));
case 1: return visitor(*reinterpret_cast<float*>(address()));
case 2: return visitor(*reinterpret_cast<std::string*>(address()));
default: assert(false);
}

Here, the address() function returns a pointer to the internal storage of boost::variant<int, float, std::string>.

There's more...

If we compare this example with the first example in this recipe, we'll see the following advantages of boost::variant:

  • We know what types a variable can store

  • If a library writer of the SQL interface adds or modifies a type held by a variant, we'll get a compile-time error instead of incorrect behavior

See also

  • After reading some recipes from Chapter 4, Compile-time Tricks, you'll be able to make the visitor object so generic that it will be able to work correctly even if the underlying types change

  • Boost's official documentation contains more examples and a description of some other features of Boost.Variant, and is available at the following link:

    http://www.boost.org/doc/libs/1_53_0/doc/html/variant.html

 

Returning a value or flag where there is no value


Imagine that we have a function that does not throw an exception and returns a value or indicates that an error has occurred. In Java or C# programming languages, such cases are handled by comparing a return value from a function value with a null pointer; if it is null then an error has occurred. In C++, returning a pointer from a function confuses library users and usually requires dynamic memory allocation (which is slow).

Getting ready

Only basic knowledge of C++ is required for this recipe.

How to do it...

Ladies and gentlemen, let me introduce you to the Boost.Optional library using the following example:

The try_lock_device() function tries to acquire a lock for a device, and may succeed or not depending on different conditions (in our example it depends on the rand() function call). The function returns an optional variable that can be converted to a Boolean variable. If the returned value is equal to Boolean true, then the lock is acquired, and an instance of a class to work with the device can be obtained by dereferencing the returned optional variable:

#include <boost/optional.hpp>
#include <iostream>
#include <stdlib.h>

class locked_device {
    explicit locked_device(const char* /*param*/) {
        // We have unique access to device
        std::cout << "Device is locked\n";
    }
public:
    ~locked_device () {
        // Releasing device lock
    }

    void use() {
        std::cout << "Success!\n";
    }
    static boost::optional<locked_device> try_lock_device() {
        if (rand()%2) {
            // Failed to lock device
            return boost::none;
        }
        // Success!
        return locked_device("device name");
    }
};

int main()
{
    // Boost has a library called Random. If you wonder why it was 
    // written when stdlib.h has rand() function, see the recipe
    // "Using a true random number generator in Chapter 12, 
    // Scratching the Tip of the Iceberg
    srandom(5);
    for (unsigned i = 0; i < 10; ++i) {
        boost::optional<locked_device> t = locked_device::try_lock_device();
        // optional is convertible to bool
        if (t) {
            t->use();
            return 0;
        } else {
            std::cout << "...trying again\n";
        }
    }
    std::cout << "Failure!\n";
    return -1;
}

This program will output the following:

...trying again 
...trying again 
Device is locked 
Success! 

Note

The default constructed optional variable is convertible to a Boolean variable holding false and must not be dereferenced, because it does not have an underlying type constructed.

How it works...

The Boost.Optional class is very close to the boost::variant class but for only one type, boost::optional<T> has an array of chars, where the object of type T can be an in-place constructor. It also has a Boolean variable to remember the state of the object (is it constructed or not).

There's more...

The Boost.Optional class does not use dynamic allocation, and it does not require a default constructor for the underlying type. It is fast and considered for inclusion in the next standard of C++. The current boost::optional implementation cannot work with C++11 rvalue references; however, there are some patches proposed to fix that.

The C++11 standard does not include the Boost.Optional class; however, it is currently being reviewed for inclusion in the next C++ standard or in C++14.

See also

 

Returning an array from a function


Let's play a guessing game! What can you tell about the following function?

char* vector_advance(char* val);

Should return values be deallocated by the programmer or not? Does the function attempt to deallocate the input parameter? Should the input parameter be zero-terminated, or should the function assume that the input parameter has a specified width?

And now, let's make the task harder! Take a look at the following line:

char ( &vector_advance( char (&val)[4] ) )[4];

Please do not worry; I've also been scratching my head for half an hour before getting an idea of what is happening here. vector_advance is a function that accepts and returns an array of four elements. Is there a way to write such a function clearly?

Getting ready

Only basic knowledge of C++ is required for this recipe.

How to do it...

We can rewrite the function like this:

#include <boost/array.hpp>
typedef boost::array<char, 4> array4_t;array4_t& vector_advance(array4_t& val);

Here, boost::array<char, 4> is just a simple wrapper around an array of four char elements.

This code answers all of the questions from our first example and is much more readable than the second example.

How it works...

The first template parameter of boost::array is the element type, and the second one is the size of an array. boost::array is a fixed-size array; if you need to change the array size at runtime, use std::vector or boost::container::vector instead.

The Boost.Array library just contains an array in it. That is all. Simple and efficient. The boost::array<> class has no handwritten constructors and all of its members are public, so the compiler will think of it as a POD type.

There's more...

Let's see some more examples of the usage of boost::array:

#include <boost/array.hpp>
#include <algorithm>

// Functional object to increment value by one
struct add_1 : public std::unary_function<char, void> {
    void operator()(char& c) const {
        ++ c;
    }
    // If you're not in a mood to write functional objects,
    // but don't know what does 'boost::bind(std::plus<char>(),
    // _1, 1)' do, then read recipe 'Binding a value as a function 
    // parameter'.
};

typedef boost::array<char, 4> array4_t;
array4_t& vector_advance(array4_t& val) {
    // boost::array has begin(), cbegin(), end(), cend(), 
    // rbegin(), size(), empty() and other functions that are 
    // common for STL containers.
    std::for_each(val.begin(), val.end(), add_1());
    return val;
}

int main() {
    // We can initialize boost::array just like an array in C++11:
    // array4_t val = {0, 1, 2, 3};
    // but in C++03 additional pair of curly brackets is required.
    array4_t val = {{0, 1, 2, 3}};

    // boost::array works like a usual array:
    array4_t val_res;       // it can be default constructible and
    val_res = vector_advance(val);  // assignable
    // if value type supports default construction and assignment

    assert(val.size() == 4);
    assert(val[0] == 1);
    /*val[4];*/ // Will trigger an assert because max index is 3
    // We can make this assert work at compile-time.
    // Interested? See recipe 'Checking sizes at compile time' 
    // in Chapter 4, Compile-time Tricks.'
    assert(sizeof(val) == sizeof(char) * array4_t::static_size);
    return 0;
}

One of the biggest advantages of boost::array is that it provides exactly the same performance as a normal C array. People from the C++ standard committee also liked it, so it was accepted to the C++11 standard. There is a chance that your STL library already has it (you may try to include the <array> header and check for the availability of std::array<>).

See also

  • Boost's official documentation gives a complete list of the Boost.Array methods with a description of the method's complexity and throw behavior, and is available at the following link:

    http://www.boost.org/doc/libs/1_53_0/doc/html/boost/array.html

  • The boost::array function is widely used across recipes; for example, refer to the Binding a value as a function parameter recipe

 

Combining multiple values into one


There is a very nice present for those who like std::pair. Boost has a library called Boost.Tuple, and it is just like std::pair, but it can also work with triples, quads, and even bigger collections of types.

Getting ready

Only basic knowledge of C++ and STL is required for this recipe.

How to do it...

Perform the following steps to combine multiple values in to one:

  1. To start working with tuples, you need to include a proper header and declare a variable:

    #include <boost/tuple/tuple.hpp>
    #include <string>
    
    boost::tuple<int, std::string> almost_a_pair(10, "Hello");
    boost::tuple<int, float, double, int> quad(10, 1.0f, 10.0, 1);
  2. Getting a specific value is implemented via the boost::get<N>() function, where N is a zero-based index of a required value:

        int i = boost::get<0>(almost_a_pair);
        const std::string& str = boost::get<1>(almost_a_pair);
        double d = boost::get<2>(quad);

    The boost::get<> function has many overloads and is used widely across Boost. We have already seen how it can be used with other libraries in the Storing multiple chosen types in a container/variable recipe.

  3. You can construct tuples using the boost::make_tuple() function, which is shorter to write, because you do not need to fully qualify the tuple type:

        using namespace boost;
        
        // Tuple comparison operators are
        // defined in header "boost/tuple/tuple_comparison.hpp"
        // Don't forget to include it!
        std::set<tuple<int, double, int> > s;
        s.insert(make_tuple(1, 1.0, 2));
        s.insert(make_tuple(2, 10.0, 2));
        s.insert(make_tuple(3, 100.0, 2));
    
        // Requires C++11
        auto t = make_tuple(0, -1.0, 2);
        assert(2 == get<2>(t));
        // We can make a compile-time assert for type
        // of t. Interested? See chapter 'compile-time tricks'
  4. Another function that makes life easy is boost::tie(). It works almost as make_tuple, but adds a nonconst reference for each of the passed types. Such a tuple can be used to get values to a variable from another tuple. It can be better understood from the following example:

        boost::tuple<int, float, double, int> quad(10, 1.0f, 10.0, 1);
        int i;
        float f;
        double d;
        int i2;
    
        // Passing values from 'quad' variables
        // to variables 'i', 'f', 'd', 'i2'
        boost::tie(i, f, d, i2) = quad;
        assert(i == 10);
        assert(i2 == 1);

How it works...

Some readers may wonder why we need a tuple when we can always write our own structures with better names, for example, instead of writing boost::tuple<int, std::string>, we can create a structure:

struct id_name_pair {
    int id;
    std::string name;
};

Well, this structure is definitely more clear than boost::tuple<int, std::string>. But what if this structure is used only twice in the code?

The main idea behind the tuple's library is to simplify template programming.

There's more...

A tuple works as fast as std::pair (it does not allocate memory on a heap and has no virtual functions). The C++ committee found this class to be very useful and it was included in STL; you can find it in a C++11-compatible STL implementation in the header file <tuple> (don't forget to replace all the boost:: namespaces with std::).

The current Boost implementation of a tuple does not use variadic templates; it is just a set of classes generated by a script. There is an experimental version that uses C++11 rvalues and an emulation of them on C++03 compilers, so there is a chance that Boost 1.54 will be shipped with faster implementation of tuples.

See also

 

Reordering the parameters of function


This recipe and the next one are devoted to a very interesting library, whose functionality at first glance looks like some kind of magic. This library is called Boost.Bind and it allows you to easily create new functional objects from functions, member functions, and functional objects, also allowing the reordering of the initial function's input parameters and binding some values or references as function parameters.

Getting ready

Knowledge of C++, STL algorithms, and functional objects is required for this recipe.

How to do it...

  1. Let's start with an example. You are working with a vector of integral types provided by some other programmer. That integral type has only one operator, +, but your task is to multiply a value by two. Without bind this can be achieved with the use of a functional object:

    class Number{};
    inline Number operator + (Number, Number);
    
    // Your code starts here
    struct mul_2_func_obj: public std::unary_function<Number, Number> {
        Number operator()(Number n1) const {
            return n1 + n1;
        }
    };
    
    void mul_2_impl1(std::vector<Number>& values) {
        std::for_each(values.begin(), values.end(), mul_2_func_obj());
    }

    With Boost.Bind, it would be as follows:

    #include <boost/bind.hpp>
    #include <functional>
    
    void mul_2_impl2(std::vector<Number>& values) {
       std::for_each(values.begin(), values.end(),
           boost::bind(std::plus<Number>(), _1, _1));
    }
  2. By the way, we can easily make this function more generic:

    template <class T>
    void mul_2_impl3(std::vector<T>& values) {
       std::for_each(values.begin(), values.end(),
           boost::bind(std::plus<T>(), _1, _1));
    }

How it works...

Let's take a closer look at the mul_2 function. We provide a vector of values to it, and for each value it applies a functional object returned by the bind() function. The bind() function takes in three parameters; the first parameter is an instance of the std::plus<Number> class (which is a functional object). The second and third parameters are placeholders. The placeholder _1 substitutes the argument with the first input argument of the resulting functional object. As you might guess, there are many placeholders; placeholder _2 means substituting the argument with the second input argument of the resulting functional object, and the same also applies to placeholder _3. Well, seems you've got the idea.

There's more...

Just to make sure that you've got the whole idea and know where bind can be used, let's take a look at another example.

We have two classes, which work with some sensor devices. The devices and classes are from different vendors, so they provide different APIs. Both classes have only one public method watch, which accepts a functional object:

class Device1 {
private:
    short temperature();
    short wetness();
    int illumination();
    int atmospheric_pressure();
    void wait_for_data();
public:
    template <class FuncT>
    void watch(const FuncT& f) {
        for(;;) {
            wait_for_data();
            f(
                temperature(),
                wetness(),
                illumination(),
                atmospheric_pressure()
            );
        }
    }
};

class Device2 {
private:
    short temperature();
    short wetness();
    int illumination();
    int atmospheric_pressure();
    void wait_for_data();
public:
    template <class FuncT>
    void watch(const FuncT& f) {
        for(;;) {
            wait_for_data();
            f(
                wetness(),
                temperature(),
                atmospheric_pressure(),
                illumination()
            );
        }
    }
};

The Device1::watch and Device2::watch functions pass values to a functional object in a different order.

Some other libraries provide a function, which is used to detect storms, and throws an exception when the risk of a storm is high enough:

void detect_storm(int wetness, int temperature, int atmospheric_pressure);

Your task is to provide a storm-detecting function to both of the devices. Here is how it can be achieved using the bind function:

    Device1 d1;
    // resulting functional object will silently ignore 
    // additional parameters passed to function call
    d1.watch(boost::bind(&detect_storm, _2, _1, _4));
    ...
    Device2 d2;
    d2.watch(boost::bind(&detect_storm, _1, _2, _3));

The Boost.Bind library provides good performance because it does not use dynamic allocations and virtual functions. It is useful even when the C++11 lambda functions are not usable:

template <class FuncT>
void watch(const FuncT& f) {
    f(10, std::string("String"));
    f(10, "Char array");
    f(10, 10);
}

struct templated_foo {
    template <class T>
    void operator()(T, int) const {
        // No implementation, just showing that bound
        // functions still can be used as templated
    }
};

void check_templated_bind() {
    // We can directly specify return type of a functional object
    // when bind fails to do so
    watch(boost::bind<void>(templated_foo(), _2, _1));
}

Bind is a part of the C++11 standard. It is defined in the <functional> header and may slightly differ from the Boost.Bind implementation (however, it will be at least as effective as Boost's implementation).

See also

  • The Binding a value as a function parameter recipe says more about the features of Boost.Bind

  • Boost's official documentation contains many more examples and descriptions of advanced features. It is available at the following link:

    http://www.boost.org/doc/libs/1_53_0/libs/bind/bind.html

 

Binding a value as a function parameter


If you work with the STL library a lot and use the <algorithm> header, you will definitely write a lot of functional objects. You can construct them using a set of STL adapter functions such as bind1st, bind2nd, ptr_fun, mem_fun, and mem_fun_ref, or you can write them by hand (because adapter functions look scary). Here is some good news: Boost.Bind can be used instead of all of those functions and it provides a more human-readable syntax.

Getting ready

Read the previous recipe to get an idea of placeholders, or just make sure that you are familiar with C++11 placeholders. Knowledge of STL functions and algorithms is welcomed.

How to do it...

Let's see some examples of the usage of Boost.Bind along with traditional STL classes:

  1. Count values greater than or equal to 5 as shown in the following code:

    boost::array<int, 12> values = {{1, 2, 3, 4, 5, 6, 7, 100, 99, 98, 97, 96}};
    
    std::size_t count0 = std::count_if(values.begin(), values.end(),
          std::bind1st(std::less<int>(), 5));
    std::size_t count1 = std::count_if(values.begin(), values.end(),
          boost::bind(std::less<int>(), 5, _1));
    assert(count0 == count1);
  2. This is how we could count empty strings:

    boost::array<std::string, 3>  str_values = {{"We ", "are", " the champions!"}};
    count0 = std::count_if(str_values.begin(), str_values.end(),
          std::mem_fun_ref(&std::string::empty));
    count1 = std::count_if(str_values.begin(), str_values.end(),
          boost::bind(&std::string::empty, _1));
    assert(count0 == count1);
  3. Now let's count strings with a length less than 5:

    // That code won't compile! And it is hard to understand
    //count0 = std::count_if(str_values.begin(), 
    //str_values.end(),
    //std::bind2nd(
    //    std::bind1st(
    //        std::less<std::size_t>(),
    //        std::mem_fun_ref(&std::string::size)
    //    )
    //, 5
    //));
    // This will become much more readable,
    // when you get used to bind
    count1 = std::count_if(str_values.begin(), str_values.end(),
        boost::bind(std::less<std::size_t>(), 
        boost::bind(&std::string::size, _1), 5));
    assert(2 == count1);
  4. Compare the strings:

    std::string s("Expensive copy constructor of std::string will be called when binding");
    count0 = std::count_if(str_values.begin(), str_values.end(), std::bind2nd(std::less<std::string>(), s));
    count1 = std::count_if(str_values.begin(), str_values.end(), boost::bind(std::less<std::string>(), _1, s));
    assert(count0 == count1);

How it works...

The boost::bind function returns a functional object that stores a copy of the bound values and a copy of the original functional object. When the actual call to operator() is performed, the stored parameters are passed to the original functional object along with the parameters passed at the time of call.

There's more...

Take a look at the previous examples. When we are binding values, we copy a value into a functional object. For some classes this operation is expensive. Is there a way to bypass copying?

Yes, there is! And the Boost.Ref library will help us here! It contains two functions, boost::ref() and boost::cref(), the first of which allows us to pass a parameter as a reference, and the second one passes the parameter as a constant reference. The ref() and cref() functions just construct an object of type reference_wrapper<T> or reference_wrapper<const T>, which is implicitly convertible to a reference type. Let's change our previous examples:

#include <boost/ref.hpp>
...
std::string s("Expensive copy constructor of std::string now "
             "won't be called when binding");
count0 = std::count_if(str_values.begin(), str_values.end(), std::bind2nd(std::less<std::string>(), boost::cref(s)));
count1 = std::count_if(str_values.begin(), str_values.end(), boost::bind(std::less<std::string>(), _1, boost::cref(s)));
assert(count0 == count1);

Just one more example to show you how boost::ref can be used to concatenate strings:

void wierd_appender(std::string& to, const std::string& from) {
    to += from;
};

std::string result;
std::for_each(str_values.cbegin(), str_values.cend(), boost::bind(&wierd_appender, boost::ref(result), _1));
assert(result == "We are the champions!");

The functions ref and cref (and bind) are accepted to the C++11 standard and defined in the <functional> header in the std:: namespace. None of these functions dynamically allocate memory in the heap and they do not use virtual functions. The objects returned by them are easy to optimize and they do not apply any optimization barriers for good compilers.

STL implementations of those functions may have additional optimizations to reduce compilation time or just compiler-specific optimizations, but unfortunately, some STL implementations miss the functionality of Boost versions. You may use the STL version of those functions with any Boost library, or even mix Boost and STL versions.

See also

 

Using the C++11 move emulation


One of the greatest features of the C++11 standard is rvalue references. This feature allows us to modify temporary objects, "stealing" resources from them. As you can guess, the C++03 standard has no rvalue references, but using the Boost.Move library you can write some portable code that uses them, and even more, you actually get started with the emulation of move semantics.

Getting ready

It is highly recommended to at least know the basics of C++11 rvalue references.

How to do it...

Now, let's take a look at the following examples:

  1. Imagine that you have a class with multiple fields, some of which are STL containers.

    namespace other {
        // Its default construction is cheap/fast
        class characteristics{};
    } // namespace other
    
    struct person_info {
        // Fields declared here
        // ...
        bool is_male_;
        std::string name_;
        std::string second_name_;
        other::characteristics characteristic_;
    };
  2. It is time to add the move assignment and move constructors to it! Just remember that in C++03, STL containers have neither move operators nor move constructors.

  3. The correct implementation of the move assignment is the same as swap and clear (if an empty state is allowed). The correct implementation of the move constructor is close to the default construct and swap. So, let's start with the swap member function:

    #include <boost/swap.hpp>
    
        void swap(person_info& rhs) {
            std::swap(is_male_, rhs.is_male_);
            name_.swap(rhs.name_);
            second_name_.swap(rhs.second_name_);
            boost::swap(characteristic_, rhs.characteristic_);
        }
  4. Now put the following macro in the private section:

    BOOST_COPYABLE_AND_MOVABLE(classname)
  5. Write a copy constructor.

  6. Write a copy assignment, taking the parameter as BOOST_COPY_ASSIGN_REF(classname).

  7. Write a move constructor and a move assignment, taking the parameter as BOOST_RV_REF(classname):

    struct person_info {
        // Fields declared here
        // ...
    private:
        BOOST_COPYABLE_AND_MOVABLE(person_info)
    public:
        // For the simplicity of example we will assume that 
        // person_info default constructor and swap are very 
        // fast/cheap to call
        person_info() {}
    
        person_info(const person_info& p)
            : is_male_(p.is_male_)
            , name_(p.name_)
            , second_name_(p.second_name_)
            , characteristic_(p.characteristic_)
        {}
    
        person_info(BOOST_RV_REF(person_info) person) {
            swap(person);
        }
    
        person_info& operator=(BOOST_COPY_ASSIGN_REF(person_info) person) {
            if (this != &person) {
                 person_info tmp(person);
                 swap(tmp);
             }
            return *this;
        }
    
        person_info& operator=(BOOST_RV_REF(person_info) person) {
            if (this != &person) {
                 swap(person);
                 person_info tmp;
                 tmp.swap(person);
             }
            return *this;
        }
    
        void swap(person_info& rhs) {
        // …
        }
    
    };
  8. Now we have a portable, fast implementation of the move assignment and move construction operators of the person_info class.

How it works...

Here is an example of how the move assignment can be used:

    person_info vasya;
    vasya.name_ = "Vasya";
    vasya.second_name_ = "Snow";
    vasya.is_male_ = true;

    person_info new_vasya(boost::move(vasya));
    assert(new_vasya.name_ == "Vasya");
    assert(new_vasya.second_name_ == "Snow");
    assert(vasya.name_.empty());
    assert(vasya.second_name_.empty());

    vasya = boost::move(new_vasya);
    assert(vasya.name_ == "Vasya");
    assert(vasya.second_name_ == "Snow");
    assert(new_vasya.name_.empty());
    assert(new_vasya.second_name_.empty());

The Boost.Move library is implemented in a very efficient way. When the C++11 compiler is used, all the macros for rvalues emulation will be expanded to C++11-specific features, otherwise (on C++03 compilers) rvalues will be emulated using specific datatypes and functions that never copy passed values nor called any dynamic memory allocations or virtual functions.

There's more...

Have you noticed the boost::swap call? It is a really helpful utility function, which will first search for a swap function in the namespace of a variable (the namespace other::), and if there is no swap function for the characteristics class, it will use the STL implementation of swap.

See also

  • More information about emulation implementation can be found on the Boost website and in the sources of the Boost.Move library at http://www.boost.org/doc/libs/1_53_0/doc/html/move.html.

  • The Boost.Utility library is the one that contains boost::utility, and it has many useful functions and classes. Refer to its documentation at http://www.boost.org/doc/libs/1_53_0/libs/utility/utility.htm.

  • The Initializing the base class by the member of the derived recipe in Chapter 3, Managing Resources.

  • The Making a noncopyable class recipe.

  • In the Making a noncopyable but movable class recipe, there is more info about Boost.Move and some examples on how we can use the movable objects in containers in a portable and efficient way.

 

Making a noncopyable class


You must have almost certainly encountered situations where providing a copy constructor and move assignment operator for a class will require too much work, or where a class owns some resources that must not be copied for technical reasons:

class descriptor_owner {
    void* descriptor_;

public:
    explicit descriptor_owner(const char* params);

    ~descriptor_owner() {
        system_api_free_descriptor(descriptor_);
    }
};

The C++ compiler, in the case of the previous example, will generate a copy constructor and an assignment operator, so the potential user of the descriptor_owner class will be able to create the following awful things:

    descriptor_owner d1("O_o");  
    descriptor_owner d2("^_^");
    
    // Descriptor of d2 was not correctly freed
    d2 = d1;
    
    // destructor of d2 will free the descriptor
    // destructor of d1 will try to free already freed descriptor

Getting ready

Only very basic knowledge of C++ is required for this recipe.

How to do it...

To avoid such situations, the boost::noncopyable class was invented. If you derive your own class from it, the copy constructor and assignment operator won't be generated by the C++ compiler:

#include <boost/noncopyable.hpp>

class descriptor_owner_fixed : private boost::noncopyable {
    …

Now the user won't be able to do bad things:

    descriptor_owner_fixed d1("O_o");
    descriptor_owner_fixed d2("^_^");
    // Won't compile
    d2 = d1;
    // Won't compile either
    descriptor_owner_fixed d3(d1);

How it works...

A sophisticated reader will tell me that we can achieve exactly the same result by making a copy constructor and an assignment operator of descriptor_owning_fixed private, or just by defining them without actual implementation. Yes, you are correct. Moreover, this is the current implementation of the boost::noncopyable class. But boost::noncopyable also serves as good documentation for your class. It never raises questions such as "Is the copy constructor body defined elsewhere?" or "Does it have a nonstandard copy constructor (with a nonconst referenced parameter)?".

See also

  • The Making a noncopyable but movable class recipe will give you ideas on how to allow unique ownership of a resource in C++03 by moving it

  • You may find a lot of helpful functions and classes in the Boost.Utility library's official documentation at http://www.boost.org/doc/libs/1_53_0/libs/utility/utility.htm

  • The Initializing the base class by the member of the derived recipe in Chapter 3, Managing Resources

  • The Using the C++11 move emulation recipe

 

Making a noncopyable but movable class


Now imagine the following situation: we have a resource that cannot be copied, which should be correctly freed in a destructor, and we want to return it from a function:

descriptor_owner construct_descriptor() {
    return descriptor_owner("Construct using this string");
}

Actually, you can work around such situations using the swap method:

void construct_descriptor1(descriptor_owner& ret) {
    descriptor_owner("Construct using this string").swap(ret);
}

But such a workaround won't allow us to use descriptor_owner in STL or Boost containers. And by the way, it looks awful!

Getting ready

It is highly recommended to know at least the basics of C++11 rvalue references. Reading the Using the C++11 move emulation recipe is also recommended.

How to do it...

Those readers who use C++11 already know about the move-only classes (like std::unique_ptr or std::thread). Using such an approach, we can make a move-only descriptor_owner class:

class descriptor_owner1 {
    void* descriptor_;

public:
    descriptor_owner1()
        : descriptor_(NULL)
    {}

    explicit descriptor_owner1(const char* param)
        : descriptor_(strdup(param))
    {}

    descriptor_owner1(descriptor_owner1&& param)
        : descriptor_(param.descriptor_)
    {
        param.descriptor_ = NULL;
    }

    descriptor_owner1& operator=(descriptor_owner1&& param) {
        clear();
        std::swap(descriptor_, param.descriptor_);
        return *this;
    }

    void clear() {
        free(descriptor_);
        descriptor_ = NULL;
    }

    bool empty() const {
        return !descriptor_;
    }

    ~descriptor_owner1() {
        clear();
    }
};

// GCC compiles the following in with -std=c++0x
descriptor_owner1 construct_descriptor2() {
    return descriptor_owner1("Construct using this string");
}

void foo_rv() {
    std::cout << "C++11\n";
    descriptor_owner1 desc;
    desc = construct_descriptor2();
    assert(!desc.empty());
}

This will work only on C++11 compatible compilers. That is the right moment for Boost.Move! Let's modify our example so it can be used on C++03 compilers.

According to the documentation, to write a movable but noncopyable type in portable syntax, we need to follow these simple steps:

  1. Put the BOOST_MOVABLE_BUT_NOT_COPYABLE(classname) macro in the private section:

    class descriptor_owner_movable {
        void* descriptor_;
        BOOST_MOVABLE_BUT_NOT_COPYABLE(descriptor_owner_movable)
  2. Write a move constructor and a move assignment, taking the parameter as BOOST_RV_REF(classname):

    #include <boost/move/move.hpp>
    
    public:
        descriptor_owner_movable()
            : descriptor_(NULL)
        {}
    
        explicit descriptor_owner_movable(const char* param)
            : descriptor_(strdup(param))
        {}
    
        descriptor_owner_movable(
          BOOST_RV_REF(descriptor_owner_movable) param)
           : descriptor_(param.descriptor_)
        { 
        param.descriptor_ = NULL;
        }
    
        descriptor_owner_movable& operator=(
          BOOST_RV_REF(descriptor_owner_movable) param)
        {
          clear();
          std::swap(descriptor_, param.descriptor_);
          return *this;
        }
        // ...
    };
    
    descriptor_owner_movable construct_descriptor3() {
        return descriptor_owner_movable("Construct using this string");
    }

How it works...

Now we have a movable but noncopyable class that can be used even on C++03 compilers and in Boost.Containers:

#include <boost/container/vector.hpp>
...
    // Following code will work on C++11 and C++03 compilers
    descriptor_owner_movable movable;
    movable = construct_descriptor3();
    boost::container::vector<descriptor_owner_movable> vec;
    vec.resize(10);
    vec.push_back(construct_descriptor3());

    vec.back() = boost::move(vec.front());

But unfortunately, C++03 STL containers still won't be able to use it (that is why we used a vector from Boost.Containers in the previous example).

There's more...

If you want to use Boost.Containers on C++03 compilers and STL containers, on C++11 compilers you can use the following simple trick. Add the header file to your project with the following content:

// your_project/vector.hpp
// Copyright and other stuff goes here

// include guards
#ifndef YOUR_PROJECT_VECTOR_HPP
#define YOUR_PROJECT_VECTOR_HPP

#include <boost/config.hpp>

// Those macro declared in boost/config.hpp header
// This is portable and can be used with any version of boost 
// libraries
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
// We do have rvalues
#include <vector>

namespace your_project_namespace {
  using std::vector;
} // your_project_namespace

#else
// We do NOT have rvalues
#include <boost/container/vector.hpp>

namespace your_project_namespace {
  using boost::container::vector;
} // your_project_namespace

#endif // !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#endif // YOUR_PROJECT_VECTOR_HPP

Now you can include <your_project/vector.hpp> and use a vector from the namespace your_project_namespace:

    your_project_namespace::vector<descriptor_owner_movable> v;
    v.resize(10);
    v.push_back(construct_descriptor3());
    v.back() = boost::move(v.front());

But beware of compiler- and STL-implementation-specific issues! For example, this code will compile on GCC 4.7 in C++11 mode only if you mark the move constructor, destructor, and move assignment operators with noexcept.

See also

About the Author

  • Antony Polukhin

    If you are wondering who is Antony Polukhin and could he be trusted to teach about C++ and Boost libraries, then here are some facts:

    • Antony Polukhin currently represents Russia in international C++ standardization committee
    • He is the author of multiple Boost libraries and maintains (keeps an eye on) some of the old Boost libraries
    • He is a perfectionist: all the source codes from the book are auto tested on multiple platforms using different C++ standards.

    But let's start from the beginning.

    Antony Polukhin was born in Russia. As a child, he could speak the Russian and Hungarian languages and learned English at school. Since his school days, he was participating in different mathematics, physics, and chemistry competitions and winning them.

    He was accepted into University twice: once for taking part in a city mathematics competition and again for gaining high score in an University's mathematics and physics challenge. In his university life, there was a year when he did not participate in exams at all: he gained A's in all disciplines by writing highly difficult programs for each teacher. He met his future wife in university and graduated with honors.

    For more than three years, he worked in a VoIP company developing business logic for a commercial alternative to Asterisc. During those days he started contributing to Boost and became a maintainer of the Boost.LexicalCast library. He also started making translations to Russian for Ubuntu Linux at that time.

    Today, he works for Yandex Ltd., helps Russian speaking people with C++ standardization proposals, continues to contribute to the open source and to the C++ language in general. You may find his code in Boost libraries such as Any, Conversion, DLL, LexicalCast, Stacktrace, TypeTraits, Variant, and others.

    He has been happily married for more than five years.

    Browse publications by this author

Latest Reviews

(2 reviews total)
Nice and wide range of examples with implamentation, explanation and references to modern C++.
Buen contenido a precio ajustado
Book Title
Access this book, plus 7,500 other titles for FREE
Access now