Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Boost C++ Application Development  Cookbook

You're reading from   Boost C++ Application Development Cookbook Recipes to simplify your application development

Arrow left icon
Product type Paperback
Published in Aug 2017
Publisher Packt
ISBN-13 9781787282247
Length 438 pages
Edition 2nd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Anton Polukhin Alekseevic Anton Polukhin Alekseevic
Author Profile Icon Anton Polukhin Alekseevic
Anton Polukhin Alekseevic
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Starting to Write Your Application FREE CHAPTER 2. Managing Resources 3. Converting and Casting 4. Compile-Time Tricks 5. Multithreading 6. Manipulating Tasks 7. Manipulating Strings 8. Metaprogramming 9. Containers 10. Gathering Platform and Compiler Information 11. Working with the System 12. Scratching the Tip of the Iceberg

Storing any value in a container/variable

If you have been programming in Java, C#, or Delphi, you will definitely miss the ability of creating 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++:

typedef std::unique_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;

Getting ready

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

How to do it...

Boost offers a solution, the Boost.Any library, that 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);
some_values.push_back("Hello there!");
some_values.push_back(std::string("Wow!"));

std::string& s = boost::any_cast<std::string&>(some_values.back());
s += " That is great!";
std::cout << s;
}

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

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

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

// 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);

// Never throws. 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 types). To use this library you do not really need to know its internal implementation in detail, but here's a quick glance at the type erasure technique for the curious.

On the assignment of some variable of type T, Boost.Any instantiates a holder<T> type that may store a value of the specified type T and is derived from some base-type placeholder:

template<typename ValueType>
struct holder : public placeholder {
virtual const std::type_info& type() const {
return typeid(ValueType);
}
ValueType held;
};

A placeholder type has virtual functions for getting std::type_info of a stored type T and for cloning a stored type:

struct placeholder {
virtual ~placeholder() {}
virtual const std::type_info& type() const = 0;
};

boost::any stores ptr-- a pointer to placeholder. When any_cast<T>() is used, boost::any checks that calling ptr->type() gives std::type_info equal to typeid(T) and returns static_cast<holder<T>*>(ptr)->held.

There's more...

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

boost::any makes use of rvalue references but can not be used in constexpr.

The Boost.Any library was accepted into C++17. If your compiler is C++17 compatible and you wish to avoid using Boost for any, just replace the boost namespace with namespace std and include <any> instead of <boost/any.hpp>. Your standard library implementation may work slightly faster if you are storing tiny objects in std::any.

std::any has the reset() function instead of clear() and has_value() instead of empty(). Almost all exceptions in Boost derived 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

  • Boost's official documentation may give you some more examples; it can be found at http://boost.org/libs/any
  • The Using a safer way to work with a container that stores multiple chosen types recipe for more info on the topic
You have been reading a chapter from
Boost C++ Application Development Cookbook - Second Edition
Published in: Aug 2017
Publisher: Packt
ISBN-13: 9781787282247
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image