Showing posts with label Cpp. Show all posts
Showing posts with label Cpp. Show all posts

C++ casting

Casting is a conversion process to change data from one type to another. C++ has two types of conversions:
  1. Implicit conversion : Conversions are performed automatically by the compiler without the programmer's intervention. They are automatically performed when a value is copied to a compatible type.   For example :
    short a=2000;
    int b;
    b=a;
    Below table showing possible implicit type conversion.
    Some of these conversions may imply a loss of precision, which can signal compiler warning. This warning can prevent explicit conversions. Constructor or operator conversions in applicable conversions, which affect classes that include specific constructors or operator functions to perform conversions. For example:
    class A {};
    class B { public: B (A a) {} };
    A a;
    B b=a;
    Here, an implicit conversion happened between objects of class A and class B, because B has a constructor that takes an object of class A as parameter. Therefore implicit conversions from A to B are allowed.

  2. Explicit conversion : Conversions are performed only when explicitly specified by the programmer. 
    short a=2000;
    int b;
    b = (int) a;    // c-like cast notation
    b = int (a);    // functional notation 
    Explicit conversion on class objects also possible using below method :
    // class type-casting
    #include <iostream>
    using namespace std;
    
    class Dummy {
        float i,j;
    };
    
    class Addition {
     int x,y;
      public:
     Addition (int a, int b) { x=a; y=b; }
     int result() { return x+y;}
    };
    
    int main () {
      Dummy d;
      Addition * padd;
      padd = (Addition*) &d;
      cout << padd->result();
      return 0;
    } 
    
    In this case result will produce either a run-time error or a unexpected result. To control this type of issue C++ provides four type of casting operator : dynamic_cast, reinterpret_cast, static_cast and const_cast.
Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)

Lets discuss this one by one :

static_cast :


Format : 
static_cast<type>(expression);
Example : 
double d=3.14159265;
int i = static_cast<int>(d);

The static_cast tells the compiler to attempt to convert between two different data types. It will convert between built-in types, even when there is a loss of precision. In addition, the static_cast operator can also convert between related pointer types. static_cast used when developer knows type casting is possible, because run time compiler not checking casting worked properly or not. Therefore, it is up to the programmer to ensure that the conversion is safe.
int* pToInt = &iVariable;
float* pToFloat = &fVariable;
float* pResult = static_cast<float*>(pToInt); 
//Will not work as the pointers are not related 
//(they are of different types). 

static_cast also possible on class object by following way :
class Base {};
class Derived: public CBase {};
Base * a = new Base;
Derived * b = static_cast<Derived*>(a);
This would be valid, although b would point to an incomplete object of the class and could lead to run-time errors if de-referenced.

dynamic_cast: 


Format :
dynamic_cast<type>(expression);
Example : 
int iVariable = 10;
float fVariable = dynamic_cast<float>(iVariable); 
/*This statement converts iVariable which is of type int to float. */
dynamic_cast can be used only with pointers and references to objects. Its purpose is to ensure that the result of the type conversion is a valid complete object of the requested class. dynamic_cast requires the Run-Time Type Information (RTTI) to keep track of dynamic types. Some compilers support this feature as an option which is disabled by default. This must be enabled for runtime type checking using dynamic_cast to work properly.

dynamic_cast is always successful when we cast a class to one of its base classes:
class Base { };
class Derived: public Base { };

Base b; Base* pb;
Derived d; Derived* pd;

pb = dynamic_cast<base>(&d);     // ok: derived-to-base
pd = dynamic_cast<derived>(&b);  // wrong: base-to-derived
The second expression in this piece of code would produce a compilation error since base to derived conversions are not allowed with dynamic_cast unless the base class is polymorphic.

// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;

class Base { virtual void dummy() {} };
class Derived: public Base { int a; };

int main () {
  try {
    Base * pba = new Derived;
    Base * pbb = new Base;
    Derived * pd;

    pd = dynamic_cast<Derived*>(pba);
    if (pd==0) cout << "Null pointer on first type-cast" << endl;

    pd = dynamic_cast<Derived*>(pbb);
    if (pd==0) cout << "Null pointer on second type-cast" << endl;

  } catch (exception& e) {cout << "Exception: " << e.what();}
  return 0;
}
Output : Null pointer on second type-cast

dynamic_cast can also cast null pointers when casting performed between unrelated classes, and can also cast pointers of any type to void pointers (void*).

const_cast: 


Format :
const_cast<type>(expression);
Example :
// const_cast
#include <iostream>
using namespace std;

void print (char * str)
{
  cout << str << endl;
}

int main () {
  const char * c = "sample text";
  print ( const_cast<char *> (c) );
  return 0;
}
Output : sample text
const_cast does not cast between different types. Instead it changes the "constness" of the expression. It can make something const what was not const before, or it can make something volatile or changeable by getting rid of the const.


reinterpret_cast:


Format :
reinterpret_cast<type>(expression); 
Example :
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a);
reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.

typeid :


typeid allows to check the type of an expression: 

Format:
typeid (expression)
Example :
// typeid
#include <iostream>
#include <typeinfo>
using namespace std;

int main () {
  int * a,b;
  a=0; b=0;
  if (typeid(a) != typeid(b))
  {
    cout << "a and b are of different types:\n";
    cout << "a is: " << typeid(a).name() << '\n';
    cout << "b is: " << typeid(b).name() << '\n';
  }
  return 0;
}
Output:
a and b are of different types:
a is: int *
b is: int 

typeid  also used to keeping track of dynamic objects.When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object:

// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;

class Base { virtual void f(){} };
class Derived : public Base {};

int main () {
  try {
    Base* a = new Base;
    Base* b = new Derived;
    cout << "a is: " << typeid(a).name() << '\n';
    cout << "b is: " << typeid(b).name() << '\n';
    cout << "*a is: " << typeid(*a).name() << '\n';
    cout << "*b is: " << typeid(*b).name() << '\n';
  } catch (exception& e) { cout << "Exception: " << e.what() << endl; }
  return 0;
}
Output:
a is: class Base *
b is: class Base *
*a is: class Base
*b is: class Derived

If the type typeid evaluates is a pointer preceded by the de-reference operator (*), and this pointer has a null value, typeid throws a bad_typeid exception.

So this all about type conversion, please add your valuable comments in comment section. 

C-Style array Vs std::array

In this article we will about study C-style array vs std::array. A std::array should have same run-time performance as a c-style array. In STL there are two type of arrays, first is fixed length array means std::array and other type is dynamic array means std::vector. 

Introduced in C++11, std::array has a unique characteristic among all sequential containers of the STL, you can not adjust it size during run-time.

Initialization of std::array


std::array initialized by following ways: 

// Required header file
#include <array> 
 
// Declare an integer array with length 4
std::array<int, 4> myArray; 
// Initialization list
std::array<int, 5> myArray = { 9, 8, 5, 3, 1 };
// Uniform initialization
std::array<int, 5> myArray { 9, 8, 5, 3, 1 }; 
// The 10 elements are not initialized.
std::array<int,10> myArray ; 
The 10 elements are value-initialized to zero.
std::array<int,10> myArray {};
// Legal, elements 3 and 4 are set to zero! 
std::array<int> myArray = { 9, 7, 5}; 
// Illegal, array length must be provided
std::array<int, > myArray = { 9, 8, 5, 3, 1 };
// Illegal, too many elements in initializer list!
std::array<int, >  myArray = { 0, 1, 2, 3, 4, 5 }; 

Index access


std::array supports the index access in 3 ways :

  1. myArray[n-1]:  Access to the nth element without a check of the array boundaries.
  2. myArray.at(n-1): Access to the nth element with a check of the array boundaries. Eventually, a std::range_error exception is thrown.
  3. std::get(myArray): Access to the nth element with a check of the array boundaries at compile time. The syntax is according to std::tuplestd::get(myArray) shows the relationship of std::array with std::tuplestd::array is a homogeneous container of fixed size while std::tuple is a heterogeneous container of fixed size.

Example: C-Style array Vs std::array

#include <iostream>
#include <array>
#include <vector>
 
 
int main()
{
  // c-style array
  int array1[3] = {1, 2, 3};
 
  array1[1] = 15;
 
  std::cout << "size: " << (sizeof(array1) / sizeof(*array1)) << std::endl;
 
  for (auto element : array1)
  {
    std::cout << element << std::endl;
  }
   
  // std-style array
  std::array<int,3> array2 = { 4, 5, 6 };
 
  array2[1] = 25;
 
  std::cout << "size: " <<array2.size() << std::endl;
 
  for (auto element : array2)
  {
    std::cout << element << std::endl;
  }
}
Here, array2.size() will return array size, no need of calculation like - (sizeof(array1) / sizeof(*array1)).


Array as method parameter:


Using below way you can pass std::array as string parameter : 
#include <iostream>
#include <vector>
#include <array>

void PrintArray(int* values, int size)
{
  std::cout << "size: " << size << std::endl;
 
  for (int i = 0; i < size; ++i)
  {
    std::cout << values[i] << std::endl;
  }
}
 
void PrintArray(const std::array<int,3> &values)
{
  std::cout << "size: " << values.size() << std::endl;
 
  for (auto& value : values)
  {
    std::cout << value << std::endl;
  }
}
 
int main()
{
  int array1[3] = { 1, 2, 3 };
  PrintArray(array1, 3);
   
  std::array<int,3> array2 = { 4, 5, 6 };
  PrintArray(array2);
}

Array as return value


std::array can be used as return value. Example -
#include <iostream>
#include <vector>
#include <array>

int* CreateArray()
{
  int* array = new int[3] { 1, 2, 3 };
  return array;
}
 
std::array<int,3> CreateStdArray()
{
  std::array<int,3> array = { 4, 5, 6 };
  return array;
}
 
int main()
{
  // c-style array
  int* array1 = CreateArray();
  int size = 3;   // you have to know the size of the array
 
  for (int i = 0; i < size; ++i)
  {
    std::cout << array1[i] << std::endl;
  }
 
  delete[] array1; // you have to delete the array
    
  // std-style array
  std::array<int,3> array2 = CreateStdArray();
 
  for (auto element : array2)
  {
    std::cout << element << std::endl;
  }
}
In this case called method should know data type and size of array before calling function, for variable length of array std::array is not useful.

Sort std::array


Using std::sort algorithm we can sort std::array elements. If any error occurred during execution will throw an out of range exception..

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>

int main()
{
  // c-style array
  int array1[3] = {7, 5, 3};
   
  std::sort(std::begin(array1), std::end(array1));
 
  for (auto element : array1)
  {
    std::cout << element << std::endl;
  }
   
  // std-style array
  std::array<int,3> array2 = { 7, 5, 3 };
 
  std::sort(array2.begin(), array2.end());
   
  for (auto element : array2)
  {
    std::cout << element << std::endl;
  }
}

Multi-dimensional arrays


The std::array as well as the c-style array support multidimensions. These multidimensions are designed as arrays of nested arrays. 
#include <iostream>
#include <array>
int main()
{
  // c-style array
  int array1[2][3] = { { 1, 2, 3 }, { 4, 5, 6} };
 
  array1[0][1] = 10;
   
  for (auto &row : array1)
  {
    for (auto &element : row)
    {
      std::cout << element << std::endl;
    }
  }     
 
  // std-style array
  std::array<std::array<int,3>, 2> array2{ { { 7, 8, 9 }, { 10, 11, 12 } } };
 
  array2[0][1] = 20;
 
  for (auto &row : array2)
  {
    for (auto &element : row)
    {
      std::cout << element << std::endl;
    }
  }
}

Summary


The std::array is designed as zero-overhead wrapper for c-style arrays. Therefore, it comes with all the advantages of a c-style array and ads the additional advantages of C++ containers. I would recommend to use std::arrays except you have a rare special use case which comes with good reasons to use a c-style array.

Advantages of std::array
  • Perfectly matches with the strict type system concept of c++
  • Copy semantic / no pointer decay / the array doesn’t convert to a pointer unless you explicitly ask it to
  • It knows its size
  • Range check in debug builds
  • No memory overhead beyond what it needs to hold its elements
  • Same performance as a c-style array
  • Direct support of use in STL algorithms

Disadvantages of std::array
  • Slightly more awkward syntax for declaration of the array, especially when creating multi-dimensional arrays

C++ Singleton design pattern

The singleton pattern is simplest design pattern, it involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance. Also provides a global point of access to that instance. There two important use of singleton design pattern :
  • One instance of a class is created.
  • It provides a global point of access to the object.
Let see one simple example of singleton pattern :

#include <string>

class Logger{
public:
   static Logger* Instance();
   bool openLogFile(std::string logFile);
   void writeToLogFile();
   bool closeLogFile();

private:
   Logger(){};  // Private default constructor
   Logger(Logger const&){};             // copy constructor is private
   Logger& operator=(Logger const&){};  // assignment operator is private
   static Logger* m_pInstance;  //Static member 
};

// Global static pointer
Logger* Logger::m_pInstance = NULL;  

Logger* Logger::Instance()
{
   if (!m_pInstance)   // One instance of class to be generated.
      m_pInstance = new Logger;

   return m_pInstance;
}

bool Logger::openLogFile(std::string _logFile)
{
   ...
}
Explanation :

  • instance() function returns a pointer to a static variable and thus is declared static.
  • Only instance() can call the constructor. Public access to the constructor is denied.
  • The constructor, copy constructor and assignment operator are declared as private.
  • The life of the singleton is for the duration of the application.
Usage:
Logger::Instance()->openLogFile("logFile.txt");

Examples and usages :
  1. Logger Classes - Logger class is implemented using singleton pattern and all application is using same instance of class.
  2. Configuration Classes - In application configuration class also using singleton design pattern. only one time configuration setting is loaded by application.
  3.  Accessing resources in shared mode - A singleton with synchronized methods could be used to be used to manage all the operations on the serial port.

Basic Vector Operations in c++

In our last article we learn about What is vector in C++ ? and How it is working ? So in this article we will try to explain different Vector Operations.

Different ways to Initialize a vector in c++


std::vector provides a constructor that accepts the size as an argument. It initialize the vector using default copy constructor. 

Example :
 
// Initialize vector with 3 integers
// Default value of all 3 ints will be 0.
std::vector<int> vecOfInts(3);
 
for(int x : vecOfInts)
 std::cout<<x <<std::endl;

Output:
0
0
0

Initialize a vector by filling similar copy of an element.

It's possible using overloaded constructor, it accepts the size of vector and an element as an argument, then it initializes the vector with second parameter value.

Example :

// Initialize vector to 3 string objects with value "Hi"
std::vector<std::string> vecOfStr(3, "Hi");
 
for(std::string str : vecOfStr)
 std::cout<<str<<std::endl;
Output:
Hi
Hi
Hi

Initialize a vector with an array

Vector provides an overloaded constructor, it accepts array pointer and array size as arguments.

Example:
// Create an array of string objects
std::string arr[] = {"first", "sec", "third"};

// Initialize vector with a string array
std::vector<std::string> vecOfStr(arr, arr + sizeof(arr)/sizeof(std::string));

for(std::string str : vecOfStr)
 std::cout<<str<<std::endl;
Output:

first
sec
third

Initialize a vector with std::list

Vector provides an overloaded constructor, it accepts list start pointer (iterator) and end pointer (iterator).

Example:
// Create an std::list of 3 string objects
std::list<std::string> listOfStr;
listOfStr.push_back("first");
listOfStr.push_back("sec");
listOfStr.push_back("third");


// Initialize a vector with std::list
std::vector<std::string> vecOfStr(listOfStr.begin(), listOfStr.end());

for(std::string str : vecOfStr)
  std::cout<<str<<std::endl;
Output:

first
sec
third

Initializing a vector with an other vector

Vector provides an copy constructor, it accepts other vector as arguments.

Example:
std::vector<std::string> vecOfStr;
vecOfStr.push_back("first");
vecOfStr.push_back("sec");
vecOfStr.push_back("third");

// Initialize a vector with other string object
std::vector<std::string> vecOfStr3(vecOfStr);

for(std::string str : vecOfStr3)
  std::cout<<str<<std::endl;
Output:

first
sec
third

Member Functions of Vector


push_backpush_back() is used for inserting an element at the end of the vector.

Example:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  vector<int>  v;
  v.push_back(1);  //insert 1 at the back of v
  v.push_back(2);  //insert 2 at the back of v
  v.push_back(4);  //insert 3 at the back of v

  for(vector<int>::iterator i = v.begin(); i != v.end(); i++) {
   cout << *i <<" ";   // for printing the vector
  }
}
Output:
1 2 4

insertinsert(iterator, element) method inserts the element in vector before the position pointed by iterator

Example:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  vector<int>  v;
  v.push_back(1);  //insert 1 at the back of v
  v.push_back(2);  //insert 2 at the back of v
  v.push_back(4);  //insert 3 at the back of v
  
  vector<int>::iterator i = v.begin();
  v.insert(i,3);
  for(vector<int>::iterator i = v.begin(); i != v.end(); i++) {
   cout << *i <<" ";   // for printing the vector
  }
}
Output:
3 1 2 4

Also insert function is overloaded by third argument count. This count parameter defines how many times the element is to be inserted before the pointed position.

Suppose v.insert(i,2,3); means insert 3 twice, Second parameter as count and third parameter as number which we want to insert.

Also possible to insert other vector elements using below call :
v.insert(i, v2.begin(), v2.end());
Above code will insert the elements from v2.begin() to v2.end() before index pointed by i.

pop_back : used to remove the last element from the vector.

Example:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  vector<int> v1 {10,20,30,40};
  
  v1.pop_back();  

  vector<int>::iterator it;
  
  for(it = v.begin(); it != v.end(); it++) {
      cout << *it <<" ";   // for printing the vector
  }
}
Output:
10 20 30

eraseerase(itr_pos) removes the element pointed by the iterator itr_pos. erase method can also be overloaded with an extra iterator specifying the end point of the range to be removed, i.e erase(itr_start, itr_end).

Example:
#include <iostream>
#include <vector>

using namespace std;

int main()
{
  vecto<int>v1 {10,20,30,40};
  vector<int>iterator:: it = v.begin();
  
  v.erase(it);   //removes first element from the vector

  v.erase(v1.begin(), v1.end() - 2 )  
  /*removes all the elements except last two */

  for(it = v.begin(); it != v.end(); it++) {
      cout << *it <<" ";   // for printing the vector
  }
}
Output:
30 40

resize: resize(size_type n, value_type value) method resizes the vector to n elements. If the current size of the vector is greater than n then the trailing elements are removed from the vector and if the current size is smaller than n than extra value elements are inserted at the back of the vector.

For example, If the size of the vector is 4 right now, with elements {10, 20, 30, 40} and we use resize method to resize it to size 5. Then by default a fifth element with value 0 will be inserted in the vector. We can specify the data to not be zero, by explicitly mentioning it as the value while calling the resize method.

swap:  It used interchanges value of two vectors.

If we have two vectors vec1 and vec2 and we want to swap the elements inside them, you just need to call vec1.swap(vec2), this will swap the values of the two vectors.

clear: clear() moves all the elements from the vector but do not delete the vector.

size: size() returns the size of the vector.

capacity: capacity() returns actual size allocated for vector.

at: at(i) returns the element at ith index in the vector.

front: front() returns the element at the front of the vector (i.e. leftmost element).

back: back() returns the element at the back of the vector (i.e. rightmost element).


Vector in C++

Vector is a template based container, some behavior like a Dynamic Array. It can expands its memory at run time and uses contiguous memory location to store elements just like Array. It stores any type of element in vector by specifying the type as template argument.

Lets see an example,
#include <vector>
int main()
{
   // This is a vector of int
    std::vector<int> vecOfInts;
 
    // While Adding it automatically adjusts it's size
    for(int i = 0; i < 10; i++)
        vecOfInts.push_back(i);
 
    std::vector<int>::iterator it = vecOfInts.begin();
    while(it != vecOfInts.end())
    {
        std::cout<<*it<<" , ";
        it++;
    }
    for(int i = 0; i < vecOfInts.size(); i++)
        std::cout<<vecOfInts[i]<<" , ";
    std::cout<<std::endl;
 
    return 0;
}

Important Points about std::vector : 


  1. Ordered Collection: In std::vector elements order will remain same in which they are inserted.
  2. Provides random access: Operator [] provides random access just like arrays. 
  3. Performance: It Performs better if insertion and deletion is in end only. It gives worst performance if insertion/deletion is at middle or at starting of vector. 
  4. Contains Copy: It always stores copy of the object not the same reference. So, if you are adding objects of user defined classes the you should define copy constructor and assignment operator in you class.

How does std::vector works internally ?


std::vector allocates a memory on heap & store all its elements in contiguous memory location. But what if memory it allocated initially is completely filled ?

First discuss about std::vector size and  std::vector capacity, Vector size means how many elements are present in vector and vector capacity means how much  continuous memory is allocated in heap for this vector, So vector capacity always greater than or equal to vector size. 

For example, let’s create a vector of integer  i.e. std::vector. Now suppose it’s initial capacity is to store 20 elements, but in our application we want to store 25 elements in it. Then what will happen when we will insert 21st element?

When std::vector’s internal memory (Capacity) completely finishes then it increases the size of its memory, by performs following steps,
  1. It will allocate a bigger chunk of memory on heap i.e. almost double the size of previously vector capacity.
  2. Then it copies all the elements from old memory location to new one. In case our elements are user defined objects then their copy constructor will be called. It makes this step quite heavy in terms of speed and performance.
  3. Then after successful copying it deletes the old memory.
Let;s check std::vector capacity and size with example :

#include <iostream>
#include <vector>
using namespace std;

struct Sample
{
    Sample(){}
    Sample(const Sample & obj)
    {
        std::cout<<"Sample copy constructor"<<std::endl;
    }
};
int main()
{
    std::vector<Sample> vecOfInts;
 
    std::cout<<"Capacity :: "<<vecOfInts.capacity()<<std::endl;
    std::cout<<"Size :: "<<vecOfInts.size()<<std::endl;
    int capcity = vecOfInts.capacity();
    for(int i = 0; i < capcity + 1; i++)
        vecOfInts.push_back(Samplstd::vector e());
 
    std::cout<<"Capacity :: "<<vecOfInts.capacity()<<std::endl;
        std::cout<<"Size :: "<<vecOfInts.size()<<std::endl;
 
    for(int i = 0; i < capcity + 1; i++)
            vecOfInts.push_back(Sample());
 
    std::cout<<"Capacity :: "<<vecOfInts.capacity()<<std::endl;
    std::cout<<"Size :: "<<vecOfInts.size()<<std::endl;
 
    return 0;
}


How to use vector efficiently in C++?

  1. Vector will be more efficient if elements are inserted or removed from the back-end only.

    As, vector internally stores all the elements in consecutive memory location. Therefore, if an element is added in middle, then vector right shifts all the right side elements of that location by 1. Also, if elements were user defined objects then copy constructors for all those elements are called.

    Similarly If element is erased from the middle, then vector left shifts all the right side elements of that location by 1. Also, if elements were user defined objects then copy constructors for all those elements are called.

    But if elements are inserted or deleted from the back-end only then this costly shifting will not happen.

  2.  Set the storage of vector initially using reserve() member function.

    As vector is a kind of container in which user can store unlimited elements. Internally it allocates storage to store the elements but during insertion if new memory requirement surpasses the current capacity then it allocates a bigger chunk of storage and copies all the existing elements there. It’s a huge burden for application because if elements in vector are user defined objects then in every new movement to new storage location copy constructor of elements will be called.

    We can avoid this if in our application by reserving the vector capacity initially by calling reserve() function. This reserve() function requests the vector capacity to be at least enough to contain n elements. It only increases the vector’s capacity, size remains same.

  3. Instead of adding single element in multiple calls, large set of elements is added in single call

    Adding single element can cause,
    1. Shifting of some elements in vector
    2. Allocation of new memory and movement of all elements on new location
    If we add a single element multiple times than all the above things can happen multiple times. Whereas, if we insert elements in together i.e. in a set than this shifting and copying can happen only once. vector can check if it has the capacity to store n elements or not or it needs to shift some elements by n location.

Boost Library in C++

In this blog we will discuss about Boot Library in C++ 11. Boost is a set of libraries for the C++ programming language that provide support for tasks and structures such as pseudo random number generation, linear algebra, image processing, multi-threading,  regular expressions, and unit testing. It contains eighty plus individual libraries, most of the Boost libraries are licensed under the Boost Software License, designed to allow Boost to be used with both free and proprietary software projects. 

Advantages of Boost library :
  1. Open Source Library.
  2. Cross Platform Development. 
  3. STL library support available.
  4. Well documented, document available on www.boost.org
  5. Good execution performance. 
  6. Easy and readable coding possible with boost library. 

Installation procedure of boost :


Use this link for installation :
  1. Unix :  Getting Started on Unix
  2. Windows : Getting Started on Windows

What Does Boost Provide?


Smart Pointers: There are some limitation of  std::auto_ptr's like - cannot be stored within a standard containers,  cannot be used to implement the pImpl (pointer-to-implementation) idiom and also does not work with arrays. In Boost library 5 type for smart pointers created to overcome this problem.

Any : In C++ 11 auto datatype is created , but auto we can use only inside function, to pass as function parameter auto can't be useful. Boost::any is more power full than Auto. Any is useful when you are working with design pattern.

Bind and Function : boost::bind and boost::function  are specified as two separate components, but they are extensions (any number of arguments) of binders and functors concept which are currently in place in the Standard Library.

The Lambda Library : Powerful lambda library is provided  by boost to work with  boost::bind and boost::function.

The Boost Graph Library : The Boost Graph Library is a huge library, with a large amount of support material and good sample programs. 

Thread : The threads library makes it seem almost as easy to do threads in C++ .

Spirit parser generator framework : Parser framework is added to work with XML.

What Else?
  • Regular Expressions
  • Traits
  • File System
  • Iterator Adaptors
  • Maths and Matrices
  • A Template metaprogramming framework
  • Tuples
  • Python

Simple Program using Boost Library : 


1)
#include <iostream>
#include "boost/any.hpp"
int main()
{
boost::any var1 = 5;
std::cout << boost::any_cast<int>(var1) <<std::endl;
int i = boost::any_cast<int>(var1);
std::cout << i <<std::endl;
return 0;
}

Output: 5 5

2)
//It will cause boost::bad_any_cast exception,
#include <iostream>
#include "boost/any.hpp"
int main()
{
try
{
boost::any var1 = 5;
std::cout << boost::any_cast<std::string>(var1) <<std::endl;
}
catch(boost::bad_any_cast &e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
Output:
boost::bad_any_cast: failed conversion using boost::any_cast

Lambdas in C++

In this blog we will discuss, What is a Lambdas in C++ ? and How to use Lambda function as callbacks ?

What is a Lambda Function?

Lambda functions are a kind of anonymous functions in C++. Lambda function is work like a normal function .
  • Input - pass arguments 
  • Output -  returns result
Lambda function doesn’t have any name. Its mainly used to create very small functions to pass as a callback to an another API.

Lets start with what was the need of lambda functions ?

Suppose I have an array of int and I want to transverse array using  STL algorithm std::for_each.

#include <iostream>
#include <algorithm>

void display(int a)
{
    std::cout<<a<<" ";
}
int main()
{
    int arr[] = { 1, 2, 3, 4, 5 };

    std::for_each(arr, arr + sizeof(arr) / sizeof(int), &display);

    std::cout << std::endl;

}
Now with Lambdas :
#include <iostream>
#include <algorithm>
 
int main()
{
    int arr[] = { 1, 2, 3, 4, 5 };
 
    std::for_each(arr, arr + sizeof(arr) / sizeof(int), [](int x) {
            std::cout <<x <<" ";
        });
 
    std::cout << std::endl;
 
}
Here, without creating extract function we can display array elements, It is more readable than first example.
  • [] is used to pass the outer scope elements (passed by value or passed by reference)
  • (int x) is showing argument x is passed

Basic Syntax for Lambda Expressions

The following line shows the basic syntax for C++11 lambda expressions:
[ captures ] (parameters) -> returnTypes { lambda Statements; }
  • [ captures ]: The capture clause, specifies which outside variables are available for the lambda function and whether they should be captured by value or by reference. An empty capture clause [] means nothing captured, in this case lambda expression body doesn't access variables in the enclosing scope.
  • ( parameters ): This is the optional parameters list, you can omit the parameters list if you want a function that takes zero arguments.
  • -> returnType: This is the optional return type.  Most of the time, compilers can find the return type of the lambda expression when you have zero or one return statement. However, it is good to write return type to understand the code.
  • { lambda Statements; }: This is the lambda body. The statements within the lambda body can the captured variables and the parameters.

Pass Outer scope elements inside lambda functions:

1) Using [=] : Outer scope elements has been passed by value
Example:
[=](int &x) {}

2) Using [&] : Outer scope elements has been passed by reference
Example: 
[&](int &x) {}

Lets see example to pass outer scope elements:

Exmaple 1 :

#include <iostream>
#include <algorithm>

int main() {
    int arr[] = { 1, 2, 3, 4, 5 };
    int add = 5;
    std::for_each(arr, arr + sizeof(arr) / sizeof(int), [&](int x) {
        std::cout << x << " ";      
        // Can modify the add inside this lambda function because
        // Can modify the add inside this lambda function because
        // all outer scope elements has write access here.
        add = 3;
        });
    std::cout << std::endl;

    std::for_each(arr, arr + sizeof(arr) / sizeof(int), [=](int &x) {
        x= x+add;
        // Can not modify the add inside this lambda function because
        // all outer scope elements has read only access here.
        // add = 9;

        });
    std::cout << std::endl;

    std::for_each(arr, arr + sizeof(arr) / sizeof(int), [](int x) {

        // No access to add inside this lambda function because
        // all outer scope elements are not visible here.
        //std::cout << add << " ";
        });
    std::cout << std::endl;
}
Example 2: ( Mixing capturing by value and Reference )
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main()
{
    int sum = 0;
    int divisor = 3;
    vector<int> numbers { 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };
    for_each(numbers.begin(), numbers.end(), [divisor, &sum] (int y)
    {
        if (y % divisor == 0)
        {
            cout << y << endl;
            sum += y;
        }
    });

    cout << sum << endl;
}
Here :
  • [=, &sum]: Captures any referenced variable within the lambda by value, except sum that has to be captured by reference.
  • [&, divisor]: Captures any referenced variable within the lambda by reference, except divisor that has to be captured by value..

Passing Lambda Expressions with std::function:

Example:
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
 
void for_each(std::function<void (int)> func)
{
    vector<int> numbers{ 1, 2, 3, 4, 5, 10, 15, 20, 25, 35, 45, 50 };
 
    for_each(numbers.begin(), numbers.end(), func);
}
 
int main()
{
    auto func1 = [](int y)
    {
        cout << y << endl;
    };
 
    auto func2 = [](int z)
    {
        cout << z * 2 << endl;
    };
 
    for_each(func1);
    for_each(func2);
}
The for_each function receives a std::function<void (int)>, so it is possible to call this function with a lambda expression that returns void and receives an int as an argument.

Here I provided some example for Lambdas in C++. There are many more things about Lambda Function, I will provide more details about Lambda in my next blogs. 

C++ "Hello World!" Program

Let's start first C++ program with "Hello World!"
#include <iostream>
using namespace std;

int main() 
{
    cout << "Hello World!";
    return 0;
}

Let's discuss code line by line.

  1. First line includes library iostream, which is required to handle input-output. This library need to include because it is not part of standard C++ Library. 
  2. In second line used to add namescpase. namescpase is group/region of classes, public method and public variables. Here we are using std Library, means C++ standard library.
  3. int main() is first function in C++, which will call first while execution. int is return type, which will return program status to outside world. Default return type in C++ is int. We can use void also.
  4. cout is the object of class ostream. It uses operator overloading to print "Hello World!".
  5. return 0 is status to other program from current program. 0 means successful execution. Non-zero value for error code.