Boost library

Kapilgarg
kapil16garg
Published in
9 min readNov 23, 2021

Boost libraries are intended to be widely useful, and usable across a broad spectrum of applications.

For example, they are helpful for handling large numbers having a range beyond the long long, long double data type (264) in C++.

Big Integer data type We can use either int128_t, int256_t, int512_t or int1024_t data type according to your requirement. By using this one, we can achieve precision up to 1024 easily. Below C++ implementation code for finding the product of large numbers.

Arbitrary precision data type: We can use any precision with the help of the cpp_int data type if we are not sure about how much precision is needed in the future. It automatically converts the desired precision at the Run-time.

Multiprecsion float: With Boost Multiprecision float, we can achieve precision up to 50 and 100 decimal with cpp_float_50 and cpp_dec_float_100 respectively. Below is C++ code to calculate the area of a circle with different precision by using a float, decimal, and cpp_float_50 type.

Now Move forward — — →

  • Boost provides lots of useful facilities not available in STL.
  • Boost provides alternatives to work around certain problems with STL’s design or implementation.
  • Boost does a good job of handling some of the very complicated problems, such as smart pointers.

Smart pointer :

A smart pointer is an object that acts as a pointer for most intents and purposes but avoids most of the Problems and purposes.

We all know New allocates memory and delete, deallocates the memory, a smart pointer is a way to automate that process, smart pointer means when we call “new”, we don’t call delete.

Unique pointer: Unique pointer is a scoped pointer, when that pointer goes out of scope It will get destroyed, and it will call delete, we can’t do a copy of the unique pointer, this is I am saying Because if it is not unique pointer, we have a two-pointer that is pointing same block memory If one of them dies, it will free up that memory, but second unique pointer we had pointed to the same block memory that has been free so you can not copy unique pointer, a unique pointerpoint actual pointer we want means each pointer can point unique object, the unique pointer is derived when you want Scope pointer.

Program :

Public :

Entity()

{

Cout << “Created entity!” << endl;

}

~Entity()

{

Cout << “Destroyed entity!” << endl;

}

Int main()

{

//local scope

{

Unique_ptr<Entity>entity = make_unique <Entity>( );

}

}

Output: Created entity! (when entered in local scope)

Destroyed entity! (come outside in the local scope)

— Problem: We can’t share as a parameter in a function and class.

Shared_ptr: The auto_ptr has unusual characters: copying it whether via copy constructor or copy assignment the operator sets it to null, and the copying pointer assumes ownership of the resource as we see in the the example below using auto_ptr:

#include <iostream>

#include <memory>

using namespace std;

class A{};

int main()

{

auto_ptr<A> pA(new A);

cout << pA.get() << endl;

auto_ptr<A> pB(pA);

cout << pA.get() << endl;

cout << pB.get() << endl;

return 0;

}

Output :

001B0950

00000000

001B0950

In the example, the get() method returns a pointer to the object pointed by the auto_ptr object, if any, or zero if it does not point to any object.

Note that the second output is null. So, in the copy constructor, pA transferred the ownership of A object to pB.

So this is not the right way to share a pointer By replacing auto_ptr with share_ptr, with an almost same code below, it produces the output we want to:

#include <boost/smart_ptr/shared_ptr.hpp>

#include <iostream>

#include <memory>

class A{};

int main()

{

boost::shared_ptr<A> pA(new A);

std::cout << pA.get() << std::endl;

boost::shared_ptr<A> pB(pA);

std::cout << pA.get() << std::endl;

std::cout << pB.get() << std::endl;

return 0;

}

Output is: 002C0950

002C0950

002C0950

Since copying boost::shared_ptr works as we expect, it can be used in STL containers while we cannot use std::auto_ptr for STL containers.

The major problem being solved using share_ptr is to know the correct time to delete a resource that is shared. The following example has two classes, A and B. The classes are sharing an instance of int, and store shared_ptr<int>. When we create the instances of each class, the shared_ptr,pTemp is passed to the constructors. In other words, all three shared_ptrs, are now referring to the same instance of an int. If we had used pointers to achieve such sharing of an int, each class would have had a hard time figuring out when it should be deleted. In the example, until the end of main(), the reference count is 3. If all of the pointers go out of scope, the reference count reaches 0, allowing the shared instance of int to be deleted.

shared_ptr holds an internal pointer to a resource such as a dynamically allocated object that may be shared with other objects in the program. We can have any number of shared_ptrs to the same resource. shared_ptr really does share the resource, if we change the resource with one shared_ptr, the changes also will be seen by the other shared_ptrs.

The internal pointer is deleted once the last shared_ptr to the resource is destroyed. shared_ptr uses reference counting to determine how many shared_ptrs point to the resource. Each time a new shared_ptr to the resource is created, the reference count increases, and each time one is destroyed, the reference count decreases. When the reference count reaches zero, the internal pointer is deleted and the memory is released.

shared_ptr holds an internal pointer to a resource such as a dynamically allocated object that may be shared with other objects in the program.

We can have any number of shared_ptrs to the same resource. shared_ptr really does share the resource, if we change the resource with one shared_ptr, the changes also will be seen by the other shared_ptrs. The internal pointer is deleted once the last shared_ptr to the resource is destroyed. shared_ptr uses reference counting to determine how many shared_ptrs point to the resource.

Each time a new shared_ptr to the resource is created, the reference count increases, and each time one is destroyed, the reference count decreases. When the reference count reaches zero, the internal pointer is deleted and the memory is released.

#include <boost/smart_ptr/shared_ptr.hpp>;

#include <iostream>

#include <memory>

class classA

{

boost::shared_ptr<int> ptA;

public:

classA(boost::shared_ptr<int> p) : ptA(p) {}

void setValue(int n) {

*ptA = n;

}

};

class classB

{

boost::shared_ptr<int> ptB;

public:

classB(boost::shared_ptr<int> p) : ptB(p) {}

int getValue() const {

return *ptB;

}

};

int main()

{

boost::shared_ptr<int> pTemp(new int(2013));

classA a(pTemp);

classB b(pTemp);

a.setValue(2014);

std::cout << “b.getValue() = “ << b.getValue() << std::endl;

return 0;

}

Output is:

b.getValue() = 2014

.

Weak_ptr: A pointer that does not own or automatically destroy the object it references (whose lifetime is assumed to be managed by a shared_ptr.

A weak_ptr points to the resource managed by a shared_ptr without assuming any responsibility for it. A weak_ptr points to the resource managed by a shared_ptr without assuming any responsibility for it. The reference count for a shared_ptr doesn’t increase when a weak_ptr references it. That means that the resource of a shared_ptr can be deleted while there is still a weak_ptr pointing to it. When the last shared_ptr is destroyed, the resource is deleted and any remaining weak_ptr is set to NULL. One use for weak_ptr is to avoid memory leaks caused by circular references.

A weak_ptr can’t directly access the resource it points to, we must create a shared_ptr from the weak_ptr to access the resource. There are two ways to do this.

— Boost :: function : Boost. Function provides a class called encapsulate function pointers. It is defined in boost/function.hpp.

If we work in a development environment supporting C++11, you have access to the class std::function from the header file functional.

In this case, you can ignore Boost.Function because boost::function and std::function are equivalent.

#include <boost/function.hpp>#include <iostream>#include <cstdlib>#include <cstring>int main(){boost::function<int(const char*)> f = std::atoi;std::cout << f("42") << '\n';f = std::strlen;std::cout << f("42") << '\n';}

boost::function makes it possible to define a pointer to a function with a specific signature. in above example defines a pointer f that can point to functions that expect a parameter of type const char* and return a value of type int. Once defined, functions with matching signatures can be assigned to the pointer.

In above example first assigns the function std::atoi() to f before std::strlen() is assigned to f.

Please note that types do not need to match exactly. Even though std::strlen() uses std::size_t as its return type, it can still be assigned to f.

Because f is a function pointer, the assigned function can be called using operator(). Depending on what function is currently assigned, either std::atoi() or std::strlen() is called.

Bind function —

Boost. Bind was added to the standard library with C++11 we will find the function std::bind() in the header file functional. Depending on the use case.

1)Without boost::bind()

#include <vector>

#include <algorithm>

#include <iostream>

void print(int i)

{

std::cout << i << ‘\n’;

}

int main()

{

std::vector<int> v{1, 3, 2};

std::for_each(v.begin(), v.end(), print);

}

The third parameter of std::for_each() is a function or function object that expects a sole parameter. In the above example std::for_each() passes the numbers in the container v as sole parameters, one after another, to print(). If you need to pass in a function whose signature doesn’t meet the requirements of an algorithm, it gets more difficult.

For example — if you want print() to accept an output stream as an additional parameter, you can no longer use it as is with std::for_each().

2)with boost::bind1st()

#include <vector>

#include <algorithm>

#include <functional>

#include <iostream>

class print : public std::binary_function<std::ostream*, int, void>

{

public:

void operator()(std::ostream *os, int i) const

{

*os << i << ‘\n’;

}

};

int main()

{

std::vector<int> v{1, 3, 2};

std::for_each(v.begin(), v.end(), std::bind1st(print{}, &std::cout));

}

Like Ex 1) , 2) writes all numbers in v to standard output. However, this time, the output stream is passed to print() as a parameter.

To do this, the function print() is defined as a function object derived from std::binary_function.

With Boost.Bind, you don’t need to transform print() from a function to a function object. Instead, you use the function template boost::bind(), which is defined in boost/bind.hpp.

3)with boost::bind()

#include <boost/bind.hpp>

#include <vector>

#include <algorithm>

#include <iostream>

void print(std::ostream *os, int i)

{

*os << i << ‘\n’;

}

int main()

{

std::vector<int> v{1, 3, 2};

std::for_each(v.begin(), v.end(), boost::bind(print, &std::cout, _1));

}

Ex .3 uses print() as a function, not as a function object. Because print() expects two parameters, the function can’t be passed directly to std::for_each().

Instead, boost::bind() is passed to std::for_each() and print() is passed as the first parameter to boost::bind(). Since print() expects two parameters, those two parameters must also be passed to boost::bind(). They are a pointer to std::cout and _1.

Boost :: array : — — — —

The library Boost.Array defines the class template boost::array in boost/array.hpp. boost::array is similar to std::array, which was added to the standard library with C++11. You can ignore boost::array if you work with a C++11 development environment.

With boost::array, an array can be created that exhibits the same properties as a C array. In addition, boost::array conforms to the requirements of C++ containers, which makes handling such an array as easy as handling any other container. In principle, one can think of boost::array as the container std::vector, except the number of elements in boost::array is constant.

Ex: (some function of boost::array)

#include <boost/array.hpp>

#include <string>

#include <algorithm>

#include <iostream>

int main()

{

typedef boost::array<std::string, 3> array;

array a;

a[0] = “cat”;

a.at(1) = “shark”;

*a.rbegin() = “spider”;

std::sort(a.begin(), a.end());

for (const std::string &s : a)

std::cout << s << ‘\n’;

std::cout << a.size() << ‘\n’;

std::cout << a.max_size() << ‘\n’;

}

Boost :: tuple :

The library Boost.Tuple provides a class called boost::tuple, which is a generalized version of std::pair. While std::pair can only store exactly two values, boost::tuple lets you choose how many values to store. The standard library has provided the class std::tuple . you can ignore Boost.Tuple because boost::tuple and std::tuple are identical.

#include <boost/tuple/tuple.hpp>

#include <boost/tuple/tuple_io.hpp>

#include <string>

#include <iostream>

int main()

{

typedef boost::tuple<std::string, int> animal;

animal a{“cat”, 4};

std::cout << a << ‘\n’;

}

To use boost::tuple, include the header file boost/tuple/tuple.hpp. To use tuples with streams, include the header file boost/tuple/tuple_io.hpp. Boost. Tuple doesn’t provide a master header file that automatically includes all others.

Create tuple using boost::make_tuple :

#include <boost/tuple/tuple.hpp>

#include <boost/tuple/tuple_io.hpp>

#include <iostream>

int main()

{

std::cout.setf(std::ios::boolalpha);

std::cout << boost::make_tuple(“cat”, 4, true) << ‘\n’;

}

Boost :: lambda:

The purpose of lambda functions is to make code more compact and easier to understand

std::for_each() with a lambda function

#include <boost/lambda/lambda.hpp>#include <vector>#include <algorithm>#include <iostream>int main(){std::vector<int> v{1, 3, 2};std::for_each(v.begin(), v.end(),std::cout << boost::lambda::_1 << "\n");}

Boost.Lambda provides several helpers to create nameless functions. Code is written where it should be executed, without needing to

be wrapped in a function and without having to call a function explicitly. In , std::cout << boost::lambda::_1 << “\n” is a

lambda function that expects one parameter, which it writes, followed by a new line, to standard output.

--

--