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.

Why employees quit their job?

Why employees quit their job? If you ask this question to HR person you will get answers, because of they are getting good offer. This might be one of reason, But as a employee point of view their are many reasons because of employees leave their job.
1) Boring project: Most of employees fill project is boar after working in same project 2-3 years. Nowadays most of company not accept this reason to change project, because of this employees live their job.
2) Poor HR management : Most of company HR is not touch with employee if you working in billable project or client project. Most of cases, observed HR will try to contact if you loss project , but if you working in project then all discussions depends on manager.
3) Company policies : If you read company policies you will fill Company is good, if many companies are working on hidden policies, not on written policies. For example, Policy - if employee want to work near to his hometown and our branch there they company will try for your relocation. But in reality company always checking their business need first, if that person is more important in current location then they'll try to neglect your demands. Also my second and most well-known example to employees also. Policy is - If case reported on employee like harassment, company fraud , then there will be proper in investigation will happen , if employee found guilty then he will loss his job , But reality is not like that in such case company directly asking put resignation, because company don't want to waist money in doing investigation.
4) Poor Team bounding: Because of busy project schedule manager or HR not getting time to bound Team. Because of this reason employee filling alone while working. Suppose employee X working in some critical task from someday he wants some help from team but teams are not ready to help, because of this reason he is filling alone and he might try to leave company.
5) Working on Outdated Technologies: If employees is working on old technology and now outside  company this technology is not useful then employee will fill insecure about this feature and he will try to change job.
6) Health Issue : If company environment or company location is not good for health then employee will leave job though job is good. For example , employee observed skin infection because of chemical used in company. Second weather like Mumbai and Chennai is not suitable for many people.
7) Company restrictions : Some company always restrict to employees they should work with only one organization, But if he is not satisfied with current company salary and want to work outside. This might be reason of employee leave their job. Other example like employee X working in company also he like to some political work outside, But company dont want employee should have direct contact with politic. 
Above issues company can control some extent. But sometimes employee also have other issues because of this employee leave his job.
1) Children Education: If employee work location dont have any education facilities, for children education many employees trying to change job.
2) Parents Health: Employee leaving job if parents need help from child.
3) Other field interest : Sometimes employee not ready to continue job in same filed.
4) Husband wife working in different locations : if Husband wife are working of different locations then any one might change job.

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

What is Data Science ?

Data science is a multidisciplinary blend of data inference, algorithms development and technology in order to solve analytically complex problems. In order to uncover useful intelligence for their organizations, data scientists must master in the full spectrum of the data science life cycle and possess a level of flexibility and understanding to maximize returns at each phase of the process. Data science is ultimately about using this data in creative ways to generate business value. 

Data Science is primarily used to make decisions and predictions making use of predictive causal analytics, prescriptive analytics and machine learning.


Data science – discovery of data insight

Discovery of data insight all about uncovering findings from data. Diving in at a granular level to mine and understand complex behaviors, inferences and trends. It is about surfacing hidden insight that can help enable companies to make smarter business decisions. For example:
  • Hotstar data mines movie viewing patterns to understand what drives user interest, and uses that to make decisions on which Hotstar original series to produce.
  • Flipkart identifies what are major customer segments within it's base and the unique shopping behaviors within those segments, which helps to guide messaging to different market audiences.
How do data scientists mine-out insights? This requires a big dose of analytical creativity and  quantitative technique in order to get a level deeper – e.g. inferential models, time series forecasting, segmentation analysis, synthetic control experiments.In this case, data scientists act as consultants, guiding business stakeholders on how to act on findings.

Data science – development of data product

A "data product" is a technical utility that utilizes data as input, and processes that data to return algorithmically generated results. The classic example of a data product is a recommendation engine or product, which ingests user data, and makes personalized recommendations based on that data. Here are some examples of data products:
  • Flipkart's recommendation engines suggest items for you to buy, determined by their algorithms. 
  • Mail spam filter is data product, an algorithm behind the scenes processes incoming mail and determines if a message is junk or not.
A data product is technical functionality that encapsulates an algorithm and is designed to integrate directly into core applications/Server. Respective examples of applications that incorporate data product behind the scenes: Flipkart's homepage, Mail inbox, and autonomous driving software. In this case, data scientists serve as technical developers, building assets that can be leveraged at wide scale.

Skills require to become Data Scientist:  

Mathematics Expertise

Mathematical statistics is important, it is not the only type of math utilized. First, there are two branches of mathematical statistics – classical statistics and Bayesian statistics. Many inferential techniques and machine learning algorithms and linear algebra. Overall, it is helpful for data scientists to have breadth and depth in their knowledge of mathematics and statistics.

Technology and Hacking

Hacking mean not breaking computer program, but creativity and ingenuity in using technical skills to build things and find clever solutions to problems. Data scientists utilize technology in order to get enormous data sets and work with complex algorithms and it requires tools far more sophisticated than Excel. 

Strong Business Acumen

Having this business acumen is just as important as having acumen for technology and algorithms. Data science projects and business goals should clearly aligned. Ultimately final value comes from leveraging all of the above to build valuable capabilities and have strong business influence.

In this blog I explain basic terms related with data science. I will try to explain more on this topic in my next blog.

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. 

Count numbers of Zero's in array without using comparison operators


Logic : For counting numbers in array we are using comparison operators, but some time interviewer will ask this question check your coding knowledge. So we can count number of zeros without using comparison operator also, by using “!” operator.

Suppose my array input is like this:
5
0
6
9
0
4
0
1
0
6

If I used “!” with each array element while traversing array then values are:
0
1
0
0
1
0
1
0
1
0
Here we know !0 = 1 and !1 = 0 also !5 = 0.

Now do sum of above array values, sum is 4. So number of zero values also 4

C program :
int zeros_in_array( int a[] , int count)
{ 
   int i, sum = 0 ;
   for (i =0 ; i < count ; i++)
   {
      sum+=!a[i];
   }
   return sum;
}
int main()
{
    int arry[] = {5,	0,	6,	9,	0,	4,	0,	1,	0,	6};
    int num = 10; // Array values count 
    printf(“Zeros in array : %d”, zeros_in_array(arry, num));
}

Count Non-Zero values in array :

Some interviewer will ask count non-zero values in array or how many non-zero values are present in array without using comparison operators?

In this case we need to use “!” operator twice with each array values. Then result array after doing twice “!” operation of with each array value:
1
0
1
1
0
1
0
1
0
1
Here we know !!0 = 0 and !!1 = 1 also !!5 = 1.

Now do sum of above array values, sum is 6. So number of non-zero values also 6.
C prograom : 
int non_zeros_in_array ( int a[] , int count)
{ 
   int i, sum = 0 ;
   for (i =0 ; i < count ; i++)
   {
      sum+=!(!a[i]);
   }
   return sum;
}
int main()
{
    int arry[] = {5,	0,	6,	9,	0,	4,	0,	1,	0,	6};
    int num = 10; // Array values count 
    printf(“Non-zero values in array : %d”, non_zeros_in_array(arry, num));
}

Check if two numbers are equal without any comparison

Logic 1: 

If two numbers are equal the bitwise XOR result will be zero. In this way we can check two numbers are equal without any comparison.

For example :

1) 5^5 = 0

(5)10 = (0101)2
0101
0101
-------
0000

2) 12^12 = 0
(12)10 = (1100)2
1100
1100
------
0000

C program :
int main()
{
    int num1 = 10, num2 = 10;
    if((num1 ^ num2) == 0)
        printf("Equal");
    else
        printf("Unequal");
    return 0;
}

Logic 2 : 

We know, subtraction of two equal numbers is Zero. Means number are zero if equal other wise non-zero.
C program :
int main()
{
    int num1 = 10, num2 = 10;
    if(!(num1 - num2))
        printf("Equal");
    else
        printf("Unequal");
    return 0;
}

Set all the bits in given range of unsigned int

First discuss about what is bits setting? 
  1. Number 12 is represented as 1100 in binary format. Mathematical representation like (12)10 = (1100)2So Number (1100)2 then complete bits setting result is (1111)2, means set all bit to 1, this is called complete/all bits setting.
  2. But in some cases we need to set particular bit of Number. For example (1100)2 set 1st bit only, then result become (1110)2, (bit counted from right to left, counting started with number 0), this is single bit setting.
  3. Now we can start with set bits of number with given range. For example (1100)2 set bits from 1st to 3rd bit, then result become (1110)2. This is given rang bits setting.
Now we can start with how to code this in C.

All bits setting:

Suppose N is unsigned integer value.
 Then we can code in C like this:
unsigned int all_bits_setting(unsigned int N)
{
  return N | ~0
}


Single bit setting:

Single bit setting is possible with following method: 
Input is (1100)2  and 2nd bit need to set, then first create binary number which contain 1 as a bit value at 1nd bit. Suppose number is X, that we can create X like this 1 << 2 = (0010)2, do OR operation of both numbers (1100)2  | (0010)2 = (1110)2

Then we can code in C like this:

unsigned int single_bit_setting(unsigned int N, unsigned int k)
{
  return (N | (1 << k)); 
}

Set given range of bits:

Input is (1100)2  and range is from 1st bit to 3rd bit. Then first create binary number which contain 1 as bit value from 1st bit to 3rd bit and other bits values are 0. So required value is (1110)2. But how to created (1110)using given rang ? So first find range difference i.e. 3 -1 = 2, then (1 <<  (2+1)) -1 = (7)10 = (0111)2 , Now shift this value with lowest rang value  (0111)2  << 1 = (1110)2, Now do OR operation of Input value  (1101)2 and (1110)2 ,
(1100)2 | (1110)=  (1110)2

Then we can code in C like this:
unsigned int rang_toggling(unsigned int N, unsigned int k , unsigned int l)
{
 //Here l > k
  return N | ((1<<(l-k)+1)-1)<<k;
}

Clear all the bits in given range of unsigned int

First discuss about what is bits clearing? 
  1. Number 12 is represented as 1100 in binary format. Mathematical representation like (12)10 = (1100)2So Number (1100)2 then complete bits clearing result is (0000)2, means set all bit to 0, this is called complete/all bits clearing.
  2. But in some cases we need to clear particular bit of Number. For example (1100)2 clear 2st bit only, then result become (1000)2, (bit counted from right to left, counting started with number 0), this is single bit clearing.
  3. Now we can start with clear bits of number with given range. For example (1101)2 clear bits from 1st to 3rd bit, then result become (0001)2. This is given rang bits clearing.
Now we can start with how to code this in C.

All bits clearing:

Suppose N is unsigned integer value.
 Then we can code in C like this:
unsigned int all_bits_clearing(unsigned int N)
{
  return N & 0
}


Single bit clearing:

Single bit clearing is possible with following method: 
Input is (1100)2  and 2nd bit need to clear, then first create binary number which contain 1 as a bit value at 2nd bit. Suppose number is X, that we can create X like this 1 << 2 = (0100)2, Now do bitwise complement of (0100)2, so binary after bitwise complement is (1011)2, do AND operation of both numbers (1100)2  & (1011)2 = (1000)2

Then we can code in C like this:

unsigned int single_bit_clearing(unsigned int N, unsigned int k)
{
  return (N & (~(1 << k))); 
}

Clear a given range of bits:

Input is (1101)2  and range is from 1st bit to 3rd bit. Then first create binary number which contain 0 as bit value from 1st bit to 3rd bit and other bits values are 1. So required value is (0001)2. But how to created (0001)using given rang ? So first find range difference i.e. 3 -1 = 2, then (1 <<  (2+1)) -1 = (7)10 = (0111)2 , Now shift this value with lowest rang value  (0111)2  << 1 = (1110)2, Now do bitwise complement of (1110)2 so binary value after bitwise complement is (0001)2 ,  Now do AND operation of Input value  (1101)2 and (0001)2 ,
(1100)& (0001)=  (0001)2

Then we can code in C like this:
unsigned int rang_toggling(unsigned int N, unsigned int k , unsigned int l)
{
 //Here l > k
  return N & ~((1<<(l-k)+1)-1)<<k;
}

Toggle a given range of bits of an unsigned int

First discuss about what is bits toggling? 
  1. Number 12 is represented as 1100 in binary format. Mathematical representation like (12)10 = (1100)2So Number (1100)then complete toggled result is (0011)2, Here 1 is replaced with 0 and 0 with 1, this is called bitwise complement.
  2. But in some cases we need to toggle particular bit of Number. For example (1100)2 toggle 1st bit only, then result become (1110)2, (bit counted from right to left, counting started with number 0), this is single bit toggling.
  3. Now we can start with toggle bits of number with given range. For example (1100)2 toggle bits from 1st to 3rd bit, then result become (0010)2. This is rang bits toggling.
Now we can start with how to code this in C.

Bitwise complement: 

Suppose N is unsigned integer value.
 Then we can code in C like this:
unsigned int bitwise_complement(unsigned int N)
{
  return ~ N
}
Operator ~ is used to get bitwise complement.


Single bit toggling:

Single bit toggle is possible with following method: 
Input is (1100)2  and 2nd bit need to toggle, then first create binary number which contain 1 as bit value at 2nd bit. Suppose number is X, that we can create X like this 1 << 2 = (0100)2, Now do XOR of both number (1100)2 ^ (0100)2 = (1000)2

Then we can code in C like this:

unsigned int single_bit_toggling(unsigned int N, unsigned int k)
{
  return (N ^ (1 << k)); 
}

Toggle a given range of bits:

Input is (1100)2  and range is from 1st bit to 3rd bit. Then first create binary number which contain 1 as a bit value from 1st bit to 3rd bit and other bits values are 0. So required value is (1110)2. But how to created (1110)2 using given rang ? So first find range difference i.e. 3 -1 = 2, then (1 <<  (2+1)) -1 = (7)10 = (0111)2 , Now shift this value with lowest rang value  (0111)<< 1 = (1110)2, This is required value to do XOR with input
(1100)2 ^ (1110)2 =  (0010)2

Then we can code in C like this:
unsigned int rang_toggling(unsigned int N, unsigned int k , unsigned int l)
{
 //Here l > k
  return N ^ ((1<<(l-k)+1)-1)<<k;
}

How can I get job in IT sector in India ?

Information technology is growing very fast in India. Bangalore, Chennai, Hyderabad, Pune and Noida are now IT hub of India. Every day many startup industries are opening, but still many engineers are waiting for job. So many engineers are still jobless in India. I don't want to discuss why this is happening and who are responsible for this condition, because there are so many factors are responsible for this and one single person can't change this. So instead of doing discussion on this topic, I want to discuss about "how to get job in IT sector"?

I want to divide my discussion into two topics. First some tips for IT engineer students, those are still pursuing engineering and second who completed IT engineering.

Tips for IT students those pursuing engineering:
  1. I know academic study is important for engineering, but with academic study you can also try some certificate course which will be helpful for next future, instead of doing local class certification, please try some international certification which is more useful than local certification.
  2. Vacation period, you can use for doing internship in any small scale company, that experience you can add into your resume.
  3. Start using open source technologies like Linux, Android, QT, WordPress etc This technologies are open source, so no money is required to buy/view code.
  4. Start using development tools like Visual studio, eclipse and Android Studio, which will let you know about how project development is happening. 
  5. Start using Open Source Version control tools Like GIT, these tools are useful to maintain project with previous versions.
  6. Those students want to work in mobile application domain, then create 2-3 Android applications and also try to publish on play store.
  7. Publish some research paper in international conference.
  8. Start writing review comments in Stackoverflow site, this will increase your knowledge as well you can add Stackoverflow points into resume.
  9. Start writing Technical blogs, there are so many blogs site available free of cost.
  10. For web developer students, create your own site, there are many web hosting sites are available with some cost.
Above points will make you resume more valuable as compare to the other IT students.
 Now some tips for IT Fresher (Engineering passout students):
  1. You also can start above steps if not done still date. Interview preparation is more important with this skills.
  2. Update your skill sets properly with technical points in resume.
  3. Publish resume on job portals, also review job portal every day and keep updating some skills and experience.
  4. Try to find job using friends circles and social media.
  5. In interview session, discuss should not be like questions answer type. It should be like common discuss, mean don't give answer like students, try to give answer like professional person with confidence.
  6. Instead of showing your need of job to interviewer try to show your abilities, try to explain how you good in IT environment.
  7. If you need job very urgently because of financial conditions then keep to two-three professional field open where you are ready to work like IT development, testing, teaching, government jobs, bank officers etc.
  8. Keep learning active while attending interview also. Some freshers showing gap between engineering passout and job interview, so interviewer might ask what you did in this period ? Be prepare for this this type of questions, with proper justified answers.
Above tips definitely will help to get job in IT sector. All tips are according to my knowledge, reader please add  your opinion in comment section which will help to get job for IT Freshers.

Please share if you like...

River, Temple and Flowers Puzzle

Puzzle -
There are 3 temples and 3 rivers. The river and the temple are alternatively.
Like -  River Temple River Temple River Temple
A man with some flowers; while crossing river, flowers gets doubled and he puts equal number of flowers in each temple. At the end no flower is left with him.

How many flowers initially person carried ?
How many flowers he put in each temple ?


Solution –

River
Temple
River
Temple
River
Temple
Flowers put in Temple

X

X

X
 Start (P)
R1
T1
R1
T2
R3
T3

Let’s assume flowers put in each temple are X

Now just think about one temple at time.
First start with temple T3; assume man have A number of flowers at start point. He have to cross 3 rivers R1,R2,R3 to reach in temple T3. So Flowers get doubled 3 times,  Hence Total number of flowers after reaching temple T3 are 2 x 2 x 2 x A = 8A

Form and
Also 8A = X and A = X/8  

Now also assume B number of Flowers for temple T2, and 2 times need to cross rivers ( R1 & R2). Hence Total number of flowers after reaching temple T3 are 2  x 2 x  B = 4B

Form and
Also 4B = X and B = X/4

Same for temple T1, assume C number of flowers required and one river need to cross.
So 2 x C = X and C= X/2  

Form ①, ③, ⑤ and
Total number of flowers required = A + B + C = X/8 + X/4 + X/2
Multiply 8 by both sides
8 x (A + B + C ) = X + 2X + 4 X = 7X

A + B + C = 7X / 8
Start putting X value form 1, 2, 3, 4, 5, 6, 7, 8, …
Only X = 8 value gives perfect integer value ( Flowers count is always Integer).
And  A + B + C = 7  

Number of flowers initially person carried  = 7
Number of flowers he puts in each temple  = 8
========================================================================
Above solution will give answer for 3 rivers and 3 temples, and flowers are increased by double while moving into river.
Now find common formula which will give answer for k number of rivers and k number of temples and flowers are increased by m times while moving into river.

Form ①, ③, ⑤ and
Total number of flowers = X/2 + X/4+ X/8 = (X + X/2 + X/4 + X/8) –X
X+ X/21 + X/22 + X/23–X      
So here k = 3 and m = 2
Sum of Geometric progression formula
a + ar + ar2  + ... + ar(n-1)  =
,  r≠1 
From ⑦  and

Let a = X, n-1 = 3 = k and r = ½ = 1/m

Total number of flowers =
Solve equation by putting available values of k and m, it will give answer in term of  x/y   (Rational Number) then x = Total number of flowers and y = Number of flowers he puts in each temple.

Let verify for 4 temples and 4 rivers, and flowers get triple after crossing river.
k = 4 and m = 3solve this equation, will get answer 40/81
Total number of flowers= 40
Number of flowers he puts in each temple = 81

========================================================================

In some cases river count is less by 1 as compare to temple, means first temple will come and then River. Like - Temple River Temple River Temple.
In that case formula become
where k= Number of temple and m times flower increased in river

Verify for 3 temples, 2 rivers and 2 times flowers increased in river
Answer in terms of x/y=7/4 is 
Total number of flowers= 7
Number of flowers he puts in each temple =

I tried to solve this puzzle in terms of mathematical equation with all scenarios. 

Please share your valuable feedback in comment section and if any correction please update in comment.