Book Image

Boost C++ Application Development Cookbook - Second Edition

By : Anton Polukhin Alekseevic
Book Image

Boost C++ Application Development Cookbook - Second Edition

By: Anton Polukhin Alekseevic

Overview of this book

If you want to take advantage of the real power of Boost and C++ and avoid the confusion about which library to use in which situation, then this book is for you. Beginning with the basics of Boost C++, you will move on to learn how the Boost libraries simplify application development. You will learn to convert data such as string to numbers, numbers to string, numbers to numbers and more. Managing resources will become a piece of cake. You’ll see what kind of work can be done at compile time and what Boost containers can do. 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. From manipulating images to graphs, directories, timers, files, networking – everyone will find an interesting topic. Be sure that knowledge from this book won’t get outdated, as more and more Boost libraries become part of the C++ Standard.
Table of Contents (19 chapters)
Title Page
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface

Combining multiple values into one


There is a very nice present for those who like std::pair. Boost has a library called Boost.Tuple. 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 a standard library is required for this recipe.

How to do it...

Perform the following steps to combine multiple values into 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);
  1. Getting a specific value is implemented via the boost::get<N>() function, where N is a zero-based index of a required value:
#include <boost/tuple/tuple.hpp>

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

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

  1. 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:
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <set>

void sample2() {
    // Tuple comparison operators are
    // defined in header "boost/tuple/tuple_comparison.hpp"
    // Don't forget to include it!
    std::set<boost::tuple<int, double, int> > s;
    s.insert(boost::make_tuple(1, 1.0, 2));
    s.insert(boost::make_tuple(2, 10.0, 2));
    s.insert(boost::make_tuple(3, 100.0, 2));

    // Requires C++11
    const auto t = boost::make_tuple(0, -1.0, 2);
    assert(2 == boost::get<2>(t));
    // We can make a compile time assert for type
    // of t. Interested? See chapter 'Compile time tricks'
}
  1. Another function that makes life easier 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:
#include <boost/tuple/tuple.hpp>
#include <cassert>

void sample3() {
    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 clearer than boost::tuple<int, std::string>. 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 the standard library. You can find it in a C++11 compatible implementation in the header file <tuple> (don't forget to replace all the boost:: namespaces with std::).

The standard library version of tuple must have multiple micro optimizations and typically provides a slightly better user experience. However, there is no guarantee on the order of construction of tuple elements, so, if you need a tuple that constructs its elements starting from the first, you have to use the boost::tuple:

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

template <int I>
struct printer {
    printer() { std::cout << I; }
};

int main() {
    // Outputs 012
    boost::tuple<printer<0>, printer<1>, printer<2> > t;
}

The current Boost implementation of a tuple does not use variadic templates, does not support rvalue references, does not support C++17 structured bindings, and is not usable with constexpr.

See also

  • Boost's official documentation contains more examples, information about performance, and abilities of Boost.Tuple. It is available at the link http://boost.org/libs/tuple.
  • The Converting all tuple elements to a string recipe in Chapter 8, Metaprogramming, shows some advanced usages of tuples.