Saturday, December 28, 2013

Stepping into C++11

C++11(formerly known as C++0x) is the latest standard in C++ programming language approved by ISO on 12 August 2011. The last standard was C++03. The naming convention of specification follows the year in which specification was published.

C++11 includes several new features to the core language and extends the C++ standard library. The principles used for enhancingC++ to C++11 are mainly
  • Maintain backward compatibility with C++03 and with C.
  • The most preferred style of introduction of new features is through standard library instead of  through core language.
  • Improve C++ to help systems and library implementations rather than useful to only to a specific application.
  • Improve typesafety by providing safe alternate techniques to previous unsafe techniques.
  • Used "zero-overhead" design principle. Any Additional support required by some utilities must be used only if utility is used.
  • Make C++ easy to teach and learn, there by eliminating the need of any utility used expert programmers.
Here is the list of some of most important features in C++11.
  • null pointer constant
  • In class member initialisation
  • Delegating constructors
  • Override
  • Final
  • static_assert
  • Type traits
  • auto
  • decltype
  • Lambdas
  • rvalue references and Move semantics
  • Variadic templates
  • std::function
  • std::bind
  • std::tuple and std::tie
  • std::initializer_list
  • Uniform initilization
  • Suffix return type syntax
  • Explicit conversion operators
  • default and delete
  • Enum class, scoped and strongly typed enums
  • constexpr - Generalised and guaranteed constant expression
  • Raw string literals
  • User defined literals
  • Range based for loops
  • Right angle brackets
  • Control and query object alignment
  • Wrapper references
  • std::unique_ptr
  • std::shared_ptr
  • std::weak_ptr
  • std::string
  • std::vector
  • STL
  • std::thread
  • std::mutex
  • std::guard_lock and std::mutex
  • std::async
  • std::future and std::promise
Here is the brief description of each of the above features.
  • null pointer constant
The meaning of "0" only in this section means "a const expression which evaluates to 0, of type int". In C and C++03 the meaning of 0  has always been an ambiguity. The preprocessor "NULL" is normally expanded to either ((void*)0) or 0. Consider the following two functions
void foo(char*);
void foo(int);
Now the statement
foo(NULL);
will always call foo(int) and this is not what the programmer wants to do.
C++11 solves this problem by introducing a new keyword "nullptr" which is of type "std::nullptr_t". Now the statement

foo(nullptr);
will certainly call "foo(char*)". Also
char* ch = nullptr; // Ok
int* i = nullptr;   // Ok
bool b = ch;        // Ok. b is false
int x = nullptr;    // error
foo(nullptr);       // call foo(char*) instead of foo(int)
  • In class member initialisation
In C++03 we cannot initialise instance members right inside the class for that we have to use constructors, C++11 does give us this freedom.
C++03 C++11

class A {
public:
    A()
    : m_a(4)
    , m_b(5)
    , m_s1("string1")
    , m_s2("string2")
    {}
    A(int a)
    : m_a(a)
    , m_b(5)
    , m_s1("string1")
    , m_s2("string2")
    {}
    A(string s)
    : m_a(4)
    , m_b(5)
    , m_s1(s)
    , m_s2("string2")
    {}
private:
    int m_a;
    int m_b;
    string m_s1;
    string m_s2;
};

class A {
public:
    A(){}
    A(int a)
    : m_a(a)
    {}
    A(string s)
    : m_s1(s)
    {}
private:
    int m_a = 4;
    int m_b = 5;
    string m_s1 = "string1";
    string m_s2 = "string2";
};
  • Delegating constructors
In C++03 classes are not allowed to call other constructors of itself. It must initialise all of its data members or must call a member method.

Consider the following example

class A {
public:
    A()
    {
        init(45);
    }
    A(int a)
    {
        init(a);
    }
private:
    void init(int a)
    {
        m_a = a;
    }
    int m_a;
};

In C++11 we would have been

class A {
public:
    A()
    : A(45)
    {
    }
    A(int a)
    : m_a(a)
    {
    }
private:
    int m_a;
};
  • Override
In C++03 it is possible to accidentally create a new virtual method when programmes is intended to override a base class method. Consider below

class A {
public:
    virtual void foo(float);
};
class B : public A {
public:
    virtual void foo(int);
};

The foo is intended to override the base class method, but since it has a different signature it will create a different virtual method. C++11 provides us with new syntax to avoid this problem.

class A {
public:
    virtual void foo(float);
};
class B : public A {
public:
    virtual void foo(int) override; // error, because it does not override a method in base class
};

The "override" identifier will make compiler to search for a method with exact same signature in base class, if it cannot find such a method than it will give an error.
  • Final
C++11 gives us the ability to prevent class inheritance and method override. This is accomplished by a new identifier "final". Consider below

Java C++11

final class Base1{}
class Derived1 extends Base1 {} // Error: Base1 has been marked as final

class Base2 {
    public final void foo(){};
}
class Derived2 extends Base2 {
    public void foo(){} // Error: foo() has been marked as final
}


struct Base1 final {};
struct Derived1 : Base1 {}; // Error: Base1 has been marked as final

struct Base2  {
    virtual void foo() final;
};
struct Derived2 : Base2 {
    virtual void foo(); // Error: foo() has been marke das final
};
  • static_assert
C++03 gives us two ways to test for assertions. First one is the macro "assert" and other is preprocessor directive "#error". Neither of these allow us to test for template and the template arguments. First checks the assertion at run time while the preprocessor test the macro at preprocess time, which is before even template is instantiated. None of these allow us to check to the template parameter.
The syntax is static_assert(constant-expression, error-message);

For example

template <typename T>
void foo(T t)
{
    static_assert(sizeof(T) == 16, "T must be of size 16  bytes");
    // do something
}
int main(int argc, const char * argv[])
{
    uint64_t i = 0;
    foo(i);
    return 0;
}
The output from clang for above code will be

Test.h:17:5: error: static_assert failed "T must be of size 16  bytes"
  • Type traits
With the help of type traits we can easily modify a program at compile time or at execution time and also we can query about certain features and primitive as well as user defined data types.  For example:
#include <type_traits>
using namespace std;
struct Foo {};
struct FooBar {
    virtual ~FooBar(){}
};
struct FooBarBar : FooBar {};

struct A {
private:
    A(A& o);
    A& operator=(A& O)const;
};
int main(int argc, const char * argv[])
{
    cout<<"float has virtual destructor "<<has_virtual_destructor<float>::value<<endl;
    cout<<"float is polymorphic "<<is_polymorphic<float>::value<<endl;
    
    cout<<"Foo has virtual destructor "<<has_virtual_destructor<Foo>::value<<endl;
    cout<<"Foo is polymorphic "<<is_polymorphic<Foo>::value<<endl;
    
    cout<<"FooBar has virtual destructor "<<has_virtual_destructor<FooBar>::value<<endl;
    cout<<"FooBar is polymorphic "<<is_polymorphic<FooBar>::value<<endl;
    
    cout<<"FooBarBar has virtual destructor "<<has_virtual_destructor<FooBarBar>::value<<endl;
    cout<<"FooBarBar is polymorphic "<<is_polymorphic<FooBarBar>::value<<endl;
    
    cout<<"uint8_t is signed "<<is_signed<uint8_t>::value<<endl;
    
    if (is_copy_constructible<A>::value && is_copy_assignable<A>::value) {
        
        cout<<"A is copyable "<<endl;
    }
    return 0;
}
Output: 

float has virtual destructor 0
float is polymorphic 0
Foo has virtual destructor 0
Foo is polymorphic 0
FooBar has virtual destructor 1
FooBar is polymorphic 1
FooBarBar has virtual destructor 1
FooBarBar is polymorphic 1
uint8_t is signed 0

  • Auto

The compiler automatically infers about the correct data type. It increases readability and verbosity of programme.

C++03 C++11

void foo(const std::unordered_map<int, int>& map) {
    
    std::unordered_map<int, int>::const_iterator it = map.begin();
    std::unordered_map<int, int>::const_iterator end = map.end();
    for (; it != end; ++it) {
        
        // other stuff
    }
}

void foo(const std::unordered_map<int, int>& map) {
    
    auto it = map.begin();
    auto end = map.end();
    for (; it != end; ++it) {
        
        // other stuff
    }
}
  • decltype
It is an operator which is used to determine the type of an expression at compile time.

C++03 C++11

int main(int argc, const char * argv[])
{
    float a = 4.5;
    const float b = 6.5;
    const float& c = a;
    float array[5];
    float *ptr;
    float local1;
    float local;
    float local3;
    float& local4 = a;
    const float local5 = 1.5;
    const float& local6 = b;
    float local7[5];
    float& local8 = a;
    float& local9 = a;
    return 0;
}


int main(int argc, const char * argv[])
{
    float a = 4.5;
    const float b = 6.5;
    const float& c = a;
    float array[5];
    float *ptr;
    decltype(a) local1;
    decltype(1.5) local2;
    decltype(2.5+3.8) local3;
    decltype(a=1.5) local4 = a; //there is no assignment a to 1.5, a == 4.5 as before
    decltype(b) local5 = 1.5;
    decltype(c) local6 = b;
    decltype(array) local7;
    decltype(array[3]) local8 = a;
    decltype(*ptr) local9 = a;
    return 0;
}
  • Lambdas
C++11 provides us with ability to define anonymous functions called lambda functions or lambda expressions.
The following example show the usage of lambdas

#include <algorithm>
#include <vector>
#include <iostream>
bool sortFunction(const int& a, const int& b)
{
    return a < b;
}
struct SortClass {
    
    bool operator()(const int& a, const int& b) const
    {
        return a < b;
    }
} sortObject;
void print(const std::vector<int>& vector)
{
    auto it = vector.begin();
    auto end = vector.end();
    for (; it != end; ++it)
        std::cout << *it << " ";
    std::cout << std::endl;
}
int main(int argc, const char * argv[])
{
    std::vector<int> v0 = {9954, -2551, -11};
    std::vector<int> v1 = {-6, -4506731};
    std::vector<int> v2 = {34, -124412, -87};
    std::vector<int> v3 = {5648, -936, -55};
    
    std::sort(v0.begin(), v0.end()); // using default comparison i.e operator <
    std::sort(v1.begin(), v1.end(), sortFunction); // using comparision function
    std::sort(v2.begin(), v2.end(), sortObject); // using comparison object
    std::sort(v3.begin(), v3.end(), [](const int& a, const int& b){ // using comparison lambda
        
        return a < b;
    });
    
    std::cout << "sorted v0 = ";
    print(v0);
    
    std::cout << "sorted v1 = ";
    print(v1);
    
    std::cout << "sorted v2 = ";
    print(v2);
    
    std::cout << "sorted v3 = ";
    print(v3);
    
    return 0;
}
The output is
sorted v0 = -25 -11 51 54 99 
sorted v1 = -45 -6 0 31 67 
sorted v2 = -87 -12 12 34 44 
sorted v3 = -55 -9 36 48 56

The argument [](const int& a, const int& b){return a < b;} is called lambda function or lambda expression. The arguments to a lambda are given inside (). The return type of a lambda is implicit, the return type is deduced from the statement or if no value is returned the default return type is void.

A lambda can access the local variables in the scope in which it is used using the syntax []. To access the local variables by reference &variableName is user and to access a local variable by value =variableName is used. To access all local variable by reference & is used and to access all local variables by value = is used.

void f()
{
    int x = 9;
    int y = 45;
    [&x](){ x += 5;}(); // Lambda can only access x by refernce, now x = 14
    /* After the execution of lambda x = 14 here because we have accessed x by reference in lambda */

}
void f()
{
    int x = 9;
    int y = 45;
    [&](){
        x += 5;
        y += 3;
    }(); // Now lambda can access all local variables by reference
    /* value of x  = 14 and y = 48 because we have accessed x and y by reference inside lambda*/
}

Lambdas can be called recursively, see below the example which calculates factorial of an int using recursive lambda
int main(int argc, const char * argv[])
{
    std::function<int (int)> factorial = [&factorial](int i) {
        
        return i <= 1 ? 1 : i * factorial(i -1);
    };
    int x = factorial(4); // x = 24
    return 0;

}
  • rvalue references and Move semantics
In C++ 03 and before temporaries(also called rvalue, as they often lie on right side of assignment) were thought to be not modifiable(just as in plain C) and are difficult to distinguish from const T& types, in other words non-const references can bind to lvalue and const references to lvalue or rvalue but there is nothing that can be bind to non-const rvalue. C++11 has introduced a new non-const reference type also called rvalue reference and is syntax is T&&. This refers to temporaries that are permitted to be modified after they are initialised.

A major performance problem in C++03 is costly and unnecessary deep copies that happen implicitly when an object is passed by value.
For example lets suppose std::vector is internally a traditional C-style array with a size. Now if such std::vector is created or returned from a function, it cane done by creating a new std::vector and copying all of rvalue data into it. Then temporary and all of its data is destroyed(For simplicity ignore return value optimisation used by some compilers).
template <typename T>
class Vector {
public:
    Vector(); // Default constructor
    Vector(const Vector&); // Copy constructor
    Vector(Vector&&); // Move constructor
    Vector& operator=(const Vector&); // Copy assignment operator
    Vector& operator=(Vector&&); // Move assignment operator
    
    virtual ~Vector(); // Destructor
private:
    T* data;
    size_t size;
};
template<typename T>
Vector<T>::Vector()
    : data(nullptr)
    , size(0)
{
}
template<typename T>
Vector<T>::Vector(Vector<T>&& o)
    : data(o.data)
    , size(o.size)
{
    o.data = nullptr;
    o.size = 0;
}
template<typename T>
Vector<T>::~Vector()
{
    if (data)
        delete[] data;
}
typedef Vector<float> Matrix;
Matrix operator*(const Matrix& a, const Matrix& b)
{
    Matrix result; // Suppose a.data = 0x003423ab
    // Matrix multiplication algorithm
    return result; //Vector(Vector&&) is called
                   // C.data = result.data and c.size = result.size
                   // result.data = nullptr and result.size = 0
} //~Vector()
  // delte result.data, okay since it is already nullptr
int main(int argc, const char * argv[])
{
    Matrix a;
    Matrix b;
    Matrix c = a * b;
    // c.data = 0x003423ab, due to move semantic of rvalue reference
    // a deep copy operation is being avoided
    return 0;
}
In order to get an rvalue reference, the function template std::move<T>() can be used.
Another example where a rvalue reference and move is used is the swap problem, traditionally a swap method will look like
template<typename T>
void swap(T& t1, T& t2)
{
    T temp(t1);
    t1 = t2;
    t2 = temp;

}
However using move we can achieve an almost perfect swap
template<typename T>
void swap(T& t1, T& t2)
{
    T temp = std::move(t1);
    t1 = std::move(t2);
    t2 = std::move(temp);
}
  • Variadic templates
Variadic templates are templates that take variable number of arguments. Before C++11 templates(both classes and functions) can only take fixed number of arguments specified at declaration of template. C++11 allows templates to take arbitrary number of arguments of any time.
template<typename... Args> class A;
The above template class will take any number of typenames as its template arguments. To create the instance of above class with three type arguments.
A<int, char, unsigned> a;
The number of arguments can be zero so A<> a; can also work well. If we do not want template to take zero number of arguments we have to modify our template definition
template<typename First, typename... Args> class A;
Variadic template can also be applied to functions as well, they not only allow type-safety to variadic functions(like printf), but also allow printf functions to take and process non-trival objects.
template<typename... Params>
void printf(const std::string& formatString, Params... params);
Please note the use of ellipsis operator (...). It has two forms. First when it appears on left side of parameter, it declares a parameter pack. Using parameter pack user can bind zero or more arguments to the variadic template parameters. Parameter pack can also be used for non-type parameters. Second when ellipsis operator occurs on the right side of template or function call argument, it unpacks the parameter pack into separate arguments like args... in the body of printf(see below). In other words use of ellipsis operator in code causes whole expression that precedes the ellipsis to repeat for every subsequent argument unpacked from argument pack, and all these expressions will be separated by comma.
The use of variadic template is often recursive. The variadic template parameters are not available to the implementation function or class. Therefore the implementation of a typical C++11 style printf would be like
void printf(const char* s)
{
    while (*s) {
        
        if (*s == '%') {
            
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                throw std::runtime_error("Invalid format string: missing arguments");
            }
        }
        std::cout << *s++;
    }
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
    while (*s) {
        if (*s == '%') {
            
            if (*(s + 1) == '%') {
                ++s;
            }
            else {
                std::cout << value;
                printf(s + 1, args...);
                return;
            }
        }
        std::cout << *s++;
    }
    throw std::logic_error("Extra arguments provided");

}
This is recursive template, please not that variadic template version of printf calls itself recursively and when args... is empty calls base case.
There is no simple mechanism to iterate over through the values of variadic templates. There are few ways to translate argument pack into a single argument use. If we intended to do so then this relays on function overloading or if the function can simply pick one argument at a time using a dumb expression marker:
template<typename... Args>inline void pass(Args&&...){}
Which can be used as follows
template<typename... Args>inline void expand(Args&&... args) {
    
    pass(some_function(args)...);
}
int main(int argc, const char * argv[])
{
    expand<int, const char*, bool>(20, "Hello", true);
    return 0;
}
Which will expand to something like this
pass(some_function(arg1), some_function(arg2), some_function(arg3) etc...);
The use of this pass function is necessary because the argument packs expands with separating by comma, but it can only be a coma of separating the function call arguments, not an "operator" function. Because of that "some_function(args)...;" will never work. Moreover, this above solution will only work when some_function return type is not void and it will do all the some_function calls in an unspecified order, because function argument evaluation order is not sequenced specifically. To avoid the unspecified order, brace enclosed initialiser list can be used, which guarantee strict left to right order evaluation. To avoid the need for a void return type, the comma operator can be used to always yield 1 in the expansion element.
struct pass {
    template<typename... T> pass(T...){}

};
pass{(some_function(args), 1)...};
Instead of executing a function a lambda can also be specified and it will be executed in place, this allows executing arbitrary sequences of elements in place
pass{([&]{std::cout << args << std::endl;}(), 1)...};
However for this particular example lambda is not necessary, simple expression can be used instead.
pass{(std::cout << args << std::endl, 1)...};

Another way is to use overloading with "termination version" of functions. This is more universal but requires a bit more code and more effort to create. One function(base version) receives one argument of some type and argument pack and other does not have any of these two(if it would have then call will ambitious for compiler, a variadic template pack alone cannot disambiguate a call).
int foo(){} // Termonation version or base case
template<typename Arg1, typename... Args>
int foo(const Arg1& arg1, const Args&... args)
{
    process(arg1);
    foo(args...); // Note arg1 does not appear here

}
If args... contains one or more arguments second version will be used and if it parameter pack is empty termination version will be used, which will eventually do nothing.

Variadic templates can also be used in exception specification, base class list and constructor's initialisation list. For example
template<typename... Base> class Child : public Base... {
public:
    Child(Base&&... base)
        : Base(base)...
    {
    }

};
The unpack parameter will replicate the types for the base classes of Child such that this class will derived from each of the types passed in. Also, constructor must take a reference to each base class, so as to initialise bases classes of Child.

In function templates, variadic parameters can be forwarded, When combined with rvalue references, this allows for perfect forwarding
template<typename T> struct SharedPtrAllocator {
    template<typename... Args> static std::shared_ptr<T> constructWithSharedPtr(Args&&... args) {
        return std::shared_ptr<T>(new T(std::forward<Args>(args)...));
    }

};
This unpacks the argument list into the constructor of T. The std::forward<Args>(args) syntax is the syntax that perfectly forwards arguments as their proper types, even with regard to rvalue-ness to the constructor. The unpack operator will propagate the forwarding syntax to each argument. This particular factory method automatically wraps the allocate memory in std::shared_ptr in order to avoid any memory leaks.

The number of arguments in a parameter pack can be determined as
template<typename... Args> struct S {
    static const int size = sizeof...(Args);

};
The syntax S<int, short>::size will be two while S<>::size will be zero.
  • std::function or function object
function objects are semantically similar in nature to function pointers and have similar syntax as well but they are loosely bound as compared to function pointers and can be made referred to any thing like member functions, function pointers or simple functions. std::function object is defined in <functional>

#include <functional>
int sum(int a, int b)
{
    return a + b;
}
int main(int argc, const char * argv[])
{
    std::function<int(int, int)> add;
    add = &sum;
    add(5, 6);
    return 0;
}

Another example

#include <functional>
int main(int argc, const char * argv[])
{
    std::plus<int> plus;
    std::function<int(int, int)> add2;
    add2 = plus;
    return 0;

}

std::plus<int> is declared inside <functional> and it can be thought of logically defined as

template<typename T>
T plus(const T& t1, const T& t2)
{
    return t1 + t2;
}
  • std::bind
It is also defined in <functional>, it takes a function(or function object or anything that can be invoked using (...) syntax) and makes a functions object with one or more than one argument(s) and bound.
Lets reconsider our previous example defined above in std::function section.

#include <functional>
int sum(int a, int b)
{
    return a + b;
}
int main(int argc, const char * argv[])
{
    auto plus = std::bind(sum, 5, 6);
    int x = plus();
    return 0;

}
Please note the use of "auto" here. 

Logically std::bind can be declared as

template<class F, class... Args>
/* unspecified */ bind (F&& f, Args&&... args);

template <class R, class F, class... Args>

/* unspecified */ bind (F&& f, Args&&... args);

The std::bind template generates a forwarding call wrapper for f. Calling this wrapper is equivalent of invoking f with its arguments bound to args.
Each argument can be either bound to a value or can be a placeholder(sometimes also called currying). The above sample is an example of bound to value, now lets see example to use placeholder arguments.

#include <functional>

float divide(float a, float b)
{
    return a / b;
}
int main(int argc, const char * argv[])
{
    auto div1 = std::bind(divide, 12, 6);
    std::cout << div1() << std::endl;
    
    auto div2 = std::bind(divide, std::placeholders::_1, std::placeholders::_2);
    std::cout << div2(12, 3) << std::endl;
    
    auto div3 = std::bind(divide, std::placeholders::_2, std::placeholders::_1);
    std::cout << div3(4, 12) << std::endl;
    return 0;

}
The Output is 
2
4
3
The _1 placeholder tells where the first argument of result of std::bind(or in this particular example of div1, div2 or div3) is to go when "divide" is called through any one of these. The first argument is called _1, the second is _2 and so on. The placeholders are defined in std::placeholders namespace.

A member function can be treated as a simple function with an extra argument.

struct A {
    int foo(int i)
    {
        return i + 5;
    }
};
int main(int argc, const char * argv[])
{
    std::function<int(A*, int)> f;
    f = &A::foo; // Its now a pointer to member function
    
    A a;
    int r = f(&a, 3); // calls A::foo() for 'a' with 3
    
    std::function<int (int)> ff = std::bind(f, &a, std::placeholders::_1);
    r = ff(7); // calls a.foo(7)
    return 0;

}
  • std::tuple and std::tie 
The tuple is N order collection of unrelated data types, where N range from 0 to large implementation defined value. Tuple can be though of an unnamed struct with members of specified tuple element types. tuple is defined in <tuple>


C++11 Python
std::tuple<int, std::string, double> t(34, "text", 2.2);
    int i = std::get<0>(t); // i = 34
    std::string s = std::get<1>(t); // s = "text"

    double d = std::get<2>(t); // d = 2.2
t = (34, 'text', 2.2)
i = t[0]
s = t[1]
d = t[2]

The elements of tuple can be explicitly specified or deuced by using make_tuple() and elements can be accessed by 0 based index using get()

auto t = std::make_tuple(std::string("hello"), 21, 56.11); // t is of type std::tuple<std::string, int, double>
    std::string s = std::get<0>(t); // s = "hello"
    int i = std::get<1>(t); // i = 21

    double d = std::get<2>(t); // d = 56.11

The unpacking of a tuple into variables can be done using std::tie

int main(int argc, const char * argv[])
{
    std::tuple<int, std::string, double> t = std::make_tuple(5, "word", 4.5);
    int i = 0;
    std::string string = "";
    double d = 0.0;
    std::tie(i, string, d) = t;
    std::cout << "i = " << i << ", string  = " << string << ", d = " << d << std::endl;
    return 0;
}
The output is
i = 5, string  = word, d = 4.5

The comparison operators(==, !=,  <, <=, > and >=) are defined for tuples of comparable element types.

std::tuple and std::tie and be used for lexicographical comparison as well.

C++03 C++11
struct Product {
    std::string name;
    float price;
    int quantity;
    bool operator < (const Product& o)
    {
        if (name < o.name)
            return true;
        if (name == o.name) {
            
            if (price < o.price)
                return true;
            if (price == o.price)
                return quantity < o.quantity;
        }
        return false;
    }
};

std::set<Product> products;
struct Product {
    std::string name;
    float price;
    int quantity;
    bool operator < (const Product& o)
    {
        return std::tie(name, price, quantity) < std::tie(o.name, o.price, o.quantity);
    }
};

std::set<Product> products;
  • Uniform initialisation and std::initilizer_list
C++03 inherited initializer list feature from C. A struct or array is given a list of arguments in braces in order of members definition in that struct. An initializer list can be recursive such as an array of struct or struct containing other structs can use these. See below an example of C++03 initlizer list

struct S {
    int i;
    std::string s;
};
S s = {1, "Text"}; // s.i = 1 and s.s = "Text"
S array[] = {{1, "First"}, {2, "Second"}};
C++03 only allows initializer list on structs or classes that conform of the definition of POD(Plain Old Data). C++11 extends initilizer-list so now they can be used on all classes like standard containers like std::vector etc.

Initilizer list is not an array anymore. C++11 has introduced a new template std::initializer_list. This allows constructors and functions to take initializer-list as parameter.

And a function that take an initilizer-list as parameter looks like
void f(std::initializer_list<float> list)
{
    // f implementation
}
int main(int argc, const char * argv[])
{
    f({2.02.53.03.5});
    return 0;
}

A possible implementation of a container that take initilizer-list as parameter in its constructor might look like this.

template<typename T>
class Vector {
public:
    Vector(std::initializer_list<T> list)
    {
        for (auto it = list.begin(); it != list.end(); ++it)
            push_back(*it);
    }
    // other implementaion

};

The constructor is a special kind of constructor called an initilizer-list constructor. Initilizer-list constructor takes precedence over other constructor if present. At sometimes a few people might confuse and intermix the initilizer-constructor with other constructor. See the example below

std::vector<int> v1(5);// constructs a vector with five elements, i.e {0, 0, 0, 0, 0}
    std::vector<int> v2{5};// constructs a vector with one element, i.e {5}
Also
struct S {
    S(int, int);
    S(std::initializer_list<int>);
};
S s1(5, 6); // calls first constructor
S s2{5, 6}; // calls initilizer_list constructor
  • Uniform initilization
struct A {
    int x;
    double y;
};
struct B {
    B(int x, double y) : _x(x) , _y(y){}
private:
    int _x;
    double _y;
};
A a{1, 2.5};
B b{1, 2.5};
The initialization of 'a' behaves exactly as though it were aggregate-initilizer. The initilization of 'b' invokes its constructor.
It may be noted that during initilizaiton implicit conversion can be used is applicable, or if no conversion exists or if narrowing conversion exists.
struct Person {
    std::string name;
    int age;
};
Person person()
{
    return {"MyName", 10};

}
And
int x = 2.5; // warning
int y{2.5}; // error: narrowing

std::vector<int> v = {2, 2.5, 45}; // eroor: narrowing
Also "The most vexing parse" problem.
















Do not mix std::initialiser_list with auto
int n = 0;
auto w(n); // int
auto x = n; // int
auto y{n}; // std::initilizer_list<int>

auto z = {n}; // std::initilizer_list<int>
  • Suffix return type syntax
Consider

template <typename T, typename U>
??? add(T t, U u)
{
    return t + u;

}

What we can write for return type? It is of course the "type of t + u". The first thought comes to mind is to use decltype
template <typename T, typename U>
decltype(t + u) add(T t, U u) // scope problem
{
    return t + u;

}
This will not work because t and u are not in scope. However we can write
template <typename T, typename U>
decltype(*(T*)(0) + *(U*)(0)) add(T t, U u)
{
    return t + u;

}
But this is ugly and error prone.
The solution is to put the return type after the arguments
template <typename T, typename U>
auto add(T t, U u) -> decltype(t + u)
{
    return t + u;

}
The auto means "return type is specified are deduced later". 
The suffix is not really about templates and type deduction but it has to do more with scope
  • Explicit conversion operators
C++98 provides implicit and explicit constructors. Which means the constructors declared explicit can only be used for explicit conversions.
struct A {
    A(int)
    {
    }
};
void f(A);
int main(int argc, const char * argv[])
{
    A a(5);
    A a2 = 5; // Silent implicit cast
    f(5); // Silent implicit cast
    return 0;
}
However if we use explicit constructor 
struct A {
    explicit A(int)
    {
    }
};
void f(A);
int main(int argc, const char * argv[])
{
    A a(5);
    A a2 = 5; // Error! implicit cast
    f(5); // Error! implicit cast
    return 0;
}
A constructor is not only method for defining a conversion. If we cannot modify a class we define a conversion operator from a  different class.
struct A {
    A(int)
    {
    }
};
struct B {
    int m;
    B(int x)
    : m(x)
    {
    }
    operator A()
    {
        return A(m);
    }
};
void f(A);
int main(int argc, const char * argv[])
{
    B b(5);
    A a = b; // Silent, implcit constructor call
    A a2(b); // Silent, implcit constructor call
    f(b); // Silent, implcit constructor call
    return 0;
}
But in C++11 we can have an explicit conversion operator as well, so the above example will look like
struct A {
    A(int)
    {
    }
};
struct B {
    int m;
    B(int x)
    : m(x)
    {
    }
    explicit operator A()
    {
        return A(m);
    }
};
void f(A);
int main(int argc, const char * argv[])
{
    B b(5);
    A a = b; // Error, explicit constructor call
    A a2(b); // Ok, explicit constructor call
    f(b); // Error, explicit constructor call
    return 0;

}
  • default and delete
C++03 provides for classes that do not provide themselves a default constructor, copy constructor, copy assignment operator(operator=) and destructor. A programmer can override these defaults by defining custom versions. C++ also provides global operators(like operator new) that work on all classes which programmer can also override. However there is very little control of creation of these defaults. For example in C++03 if one wants to make a class non-copyable one must declare copy constructor and copy assignment operator private and do not implement them(see below)
struct A {
private:
    A(const A&);
    A& operator=(const A&);
};
However in C++11 using delete we can achieve similar behavior
struct A {
    A(const A&) = delete;
    A& operator=(const A&) = delete;

};
We can use default in a similar fashion
struct A {
    int m;
    A() = default;
    A(int i)
    : m(i)
    {
    }
};
In above example we are providing an overloaded constructor that takes an int as parameter, and we specify that we will be  using default constructor.
Similarly we can even further control what type arguments can be used. For example
struct A {
    A(float); // Can initilize with float
    A(long) = delete; // But not with long
    virtual ~A() = default; // Using default destructor
};
  • Enum class, scoped and strongly typed enums
There are three problems with enums in C++03

  • The underlying type of an enum can not be specified, it is up to compiler whatever data type it chooses. This introduces compatibility issue(due to compiler differences) and enum cannot be forward declared.
  • Enums export their enumerators to the surrounding scope which may cause name conflicts.
  • Enums are not type safe, they can be implicitly converted to int which causes errors when someone does not want an enum to act as an int.

  • constexpr - Generalised and guaranteed constant expression 
In C++ we always have a concept of constant expressions. There are certain expressions which are always same both at compile time and at run time for example expression 5 + 9. Constant expressions are one of the best optimisation opportunities for compilers and modern compilers try to compute results at compile time and hardcode in the program.
int size()
{
    return 5;
}

int arr[size()]; // Error, "Variable length array declaration not allowed"
This is illegal in C++03 because size() is not a constant expression. A C++03 compiler has no way of knowing that size() is actually a constant at runtime.
C++11 has introduced another keyword constexpr that guarantees that a code block is constant at compile time. The above example can be written in C++11 as
constexpr int size()
{
    return 5;
}

int arr[size()];
It will allow the compiler to understand and verify that size() is a compile time constant.
Another example of constexpr

However using constexpr introduces some limitations on functions what it can do, these are
- Function must have a non void return type.
- Function body cannot declare variables or define new types.
- Function body may contain only declarations, null statements and single return statement.
- There must exist argument values such that after argument substitution the return steamiest must produce a constant expression.

Any member functions of classes such as copy constructor or other operators overloaded functions can be made constexpr provided that they meet the requirement of constexpr. This will allow compiler to copy classes at compile time and perform operations on them.

If a constexpr function is called with arguments which are not constexpr the function behaves as of it is a non-constexpr function and similarly in a constexpr function if its return statement does not evaluate to a constexpr for a particular case then it is not a constexpr function.

struct Point {
    int x;
    int y;
    constexpr Point(int _x, int _y)
        : x(_x)
        , y(_y)
    {
    }
};

constexpr Point origin(0, 0);
Please note that constexpr is not general purpose replacement for const and vice versa.
  • Raw string literals
In C++11 raw string literals there is no need for escape character. This is particularly useful when defining regular expressions and other similar operations.


How do we put quotes in raw string, its easy

std::string s = R"("A quoted string")";
std::cout << s << std::endl;
Output
"A quoted string"

How do we get character sequence )" into a raw string, although this is very rare case but "(...)" is the only default delimiter pair. We can add delimiters before and after (...) in "(...)". For example

std::string s = R"###("A quoted string that contains terminator (")")###";
std::cout << s << std::endl;
Output
"A quoted string that contains terminator (")"

The character sequence before ( must be identical to after ). In the above example ### can be replaced with any sting and it must be maximum of 16 characters in length.

C++11 introduced two new character types char16_t and char32_t. There are three unicode encodings that C++11 supports, these are UTF-8, UTF-16 and UTF-32.

u8R"(This is a UTF-8 string)";
uR"(This is a UTF-16 string)";

UR"(This is a UTF-32 string)";

The first one has usual data type of const char[], second one has const char16_t[] and third one has const char32_t[].

C++11 also allows us to put unicode code prints directly into the string.

u8R"(This is a Unicode Character: \u2018.)"
uR"(This is a bigger Unicode Character: \u2018.)"

UR"(This is a Unicode Character: \U00002018.)"
  • User defined literals
In C++03 we have literals for many builtin data types.
256 // int
3.5 // double
5.6f // float
'x' // char
2ULL // unsigned long long
0xAA // hexadecimal unsigned
"rb" // string
C++11 gives us the ability to define user defined literals. User defined objects are constructed through the use of string of characters.
namespace E {
struct Point {
    double x;
    double y;
    Point(double _x, double _y)
        : x(_x)
        , y(_y)
    {
    }
};
namespace Literals {
Point operator "" _p(const char* data, size_t length)
{
    std::string string(data);
    size_t position = string.find(",");
    return Point(std::stod(string.substr(0, position)), std::stod(string.substr(position + 1)));
}
}
}
using namespace E::Literals;
int main(int argc, const char * argv[])
{
    E::Point point = "1234.555,34562.3"_p;
    return 0;
}

Literal conversion takes place in two distinct stages, raw and cooked. Raw literal is sequence of characters or some specific types(not necessarily of char*) while cooked literal is of some other type.  There is an exception to this rule and that is of string literals. In the above example "1234.555,34562.3" is in raw form(as a sequence of const char*).

A C++ literal 876 is raw literal, this is the sequence of characters '8', '7', '6' and in cooked literal it is integer 876. The C++ literal 0xFF is raw '0', 'x', 'F', 'F' while in cooked for it is integer 255.

All user defined literals use suffix(it is not possible to define through prefix). All user defined suffixes must start with underscore(_) and using only underscore(_) is reserved by standard.

Another way of processing integer and floating point is through the use of variadic templates.
struct A {
    // Implementaion
};
namespace Literals {
template<char...> A operator "" _a();
}
using namespace Literals;
int main(int argc, const char * argv[])
{
    A a1 = 12345_a;
    A a2 = 5.67_a;
    return 0;
}
The instantiation of a1 takes place as operator "" _a<'1', '2', '3', '4', '5'>(). Please note that there is no terminating character in this form. This main reason of this is to make use of C++11 keyword constexpr which makes compiler to construct and transform literal completely at compile time provided that the object which is being constructed is constexpr constructable and copyable and also literal processing function is constexpr.

Literal processing function can be overloaded like other functions.
struct A {
    // Implementaion
};
namespace Literals {
A operator "" _a(const char*,     size_t);
A operator "" _a(const wchar_t*,  size_t);
A operator "" _a(const char16_t*, size_t);
A operator "" _a(const char32_t*, size_t);
}
using namespace Literals;
int main(int argc, const char * argv[])
{
    A a1 =   "12345"_a; // Uses const char* overloaded version
    A a2 = u8"12345"_a; // Uses const char* overloaded version
    A a3 =  L"12345"_a; // Uses const wchar* overloaded version
    A a4 =  u"12345"_a; // Uses const char16_t* overloaded version
    A a5 =  U"12345"_a; // Uses const char32_t* overloaded version
    return 0;

}

Please note the use of namespace in order to avoid any namespace conflict that may arise when using may user defined literals in a global namespace. An example for usage of user defined literal can be found here.
  • Range based for loops
In C++11 for loop gives us an easy way to iterate over a range of elements from a container or any object that has begin() and end() defined. We can iterate through all standard containers, an initialiser list, an array, std::string or even C-style arrays.

int main(int argc, const char * argv[])
{
    int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9,};
    std::list<int> list;
    for (auto x : array) {
        std::cout << x << std::endl;
        list.push_back(x);
    }
    for (int& i : list) // accessing each member by reference so that we are able to midify values
        ++i;
    std::cout << "After " << std::endl;
    for (auto it : list)
        std::cout << it << std::endl;
    return 0;
}
The output is
1
2
3
4
5
6
7
8
9
After 
2
3
4
5
6
7
8
9
10
  • Right angle brackets
C++03 compiler recognizes >> as right shift operator. However it may appear when instantiating nested templates, such as
std::list<std::vector<std::string>> listOfVectors;
A C++03 compiler will give an error on the above statement. If we put a space between last to right angle brackets the error will go away(however some programmers may forget to put that space). The question is why is this even a problem, we will have to look into the compilation stages in a compiler. A compiler front end consists of following stages
- Lexical analyser, it makes up tokens from characters.
- Syntax analyser, it performs the grammar checking.
- Type checking, it finds the type of names and expressions.
Theoretically these stages are independent of each other, so the lexical analyzer has no way of knowing the >> is really a right shift operator or is part of a nested template instantiation statement.
C++11 dictates an improved specification of parser, so that multiple right angle brackets are interpreted as closing template arguments where necessary. The intended behaviour can further be explicitly specified by the use of parenthesis around the parameter expressions which involve >, >=, or >> binary operators.
template<bool B> struct A;
std::vector<A<1>2>> a1;
// Interpreted as std::vector of A<true> followed by "2 >> a1"
// , which is not a legal expression. 1 is true
std::vector<A<(1>2)>> a2;
// Interpreted as std::vector of A<fasle> followed by declaration of a2

//, which is legal syntax. (1>2) is false
  • Control and query object alignment
C++11 allows us to align memory allocations according to our own desirers when dealing with low level raw memory. Two new operators are introduced in C++11, and these are alignas and alignof. 

alignof operator takes a type and returns a power of 2 byte boundary on which the instances of type must be allocated(in std::size_t). When given referenced type alignof gives the referenced type's alignment and when given array type it returns the individual element type's alignment.
constexpr size_t size = alignof(long);
size contains the alignment of type long.

alignas controls the memory alignment for a variable. It takes a constant or a type.
alignas(double) char array[5 * sizeof(double)];
In above expression we have requested an array to hold five doubles which is suitable for holding doubles.
  • Wrapper references
A wrapper reference is obtained form an instance of template class reference_wrapper. Wrapper reference are similar to normal references ('&') in C++. For obtaining wrapper reference for any object std::ref is used and for constant wrapper reference std::cref is used.
void increment(int& i)
{
    ++i;
}
template<typename T, typename U>
void foo(T t, U u)
{
    t(u);
}
int main(int argc, const char * argv[])
{
    int i = 3;
    foo(increment, i);
    // foo is instantiated as foo<void (int&), int>, i is not incremented
    
    std::cout << "i = " << i << std::endl;
    
    foo(increment, std::ref(i));
    // foo is instantiated as foo<void (int&), std::reference_wrapper<int> >, i is incremented
    
    std::cout << "i = " << i << std::endl;
    return 0;
}
It is added in <utility>.
  • std::unique_ptr
It is defined in <memory> and has following properties
- It has memory ownership of object that it holds a pointer to
- It is not copy-constructable or copy-assignable however it is move-constructable and move-assignable.
- It deletes the object it has pointer to when itself goes out of scope.
Please note that unique_ptr does what previously auto_ptr does in C++98, however auto_ptr is depreciated now in C++11.

#include <memory>
class A {
public:
    static std::unique_ptr<A> create()
    {
        std::unique_ptr<A> localPtr(new A()); // localPtr has object ownership
        return std::move(localPtr);// transfering(moving) ownership out of localPtr
    }// localPtr destructor called, its safe becaue we have already
     // transfered(moved) ownership, localPtr internal pointer is null(or more
     // correctly nullptr)
private:
    A()
    {
    }
    // Rest of implementation
};
int main(int argc, const char * argv[])
{
    std::unique_ptr<A> objPtr = A::create(); // objPtr has sole ownership of object
    return 0;
} // objPtr destructor is called, objPtr will delete its internal pointer
  • std::shared_ptr
It is used to represent the shared ownership of object memory. When a shared_ptr goes out of scope it automatically deletes the object pointed by it.

#include <memory>
class A {
public:
    static std::shared_ptr<A> create()
    {
        return std::shared_ptr<A>(new A()); // refCount = 1
    } // refCount = 2, because the return type is being creted
      // refCount = 1, because the anonymous first shared_ptr destructor is being called
private:
    A()
    {
    }
    // Rest of implementation
};
int main(int argc, const char * argv[])
{
    std::shared_ptr<A> objPtr = A::create(); // refCount = 2, objPtr is created, then refCount = 1 because the return value is being destroyed
    {
        std::shared_ptr<A> anotherPtr = objPtr; // refCount = 2
        {
            std::shared_ptr<A> yetAnotherPtr(anotherPtr); // refCount = 3
            // other stuff ......
        } // refCount = 2, yetAnotherPtr destructor is being called here;
    } // refCount = 1, anotherPtr destructor is being called here
    return 0;
} // weakCount = 0, weakPtr1 destructor is called here and object being
  // pointed is being deleted here
  • std::weak_ptr
Miss use of shared_ptr may result in certain scenarios which are not desirable, such as consider when two objects hold a strong pointer to each other, here strong means both had a shared_ptr pointing to each other, now in this particular case cycles are introduced and neither of the objects gets deleted(their refCount will never reach zero). std::weak_ptr are used in such cases to break the ref-counted cycles. These are used when one needs to access object only when it exists, it must get deleted by someone else and its destructor must be called after its last use. The above example in shared_ptr can be modified to give a glimpse of std::weak_ptr, see below
#include <memory>
class A {
public:
    static std::shared_ptr<A> create()
    {
        return std::shared_ptr<A>(new A()); // refCount = 1
    } // refCount = 2, because the return type is being creted
      // refCount = 1, because the anonymous first shared_ptr destructor is being called
private:
    A()
    {
    }
    // Rest of implementation
};
int main(int argc, const char * argv[])
{
    std::shared_ptr<A> objPtr = A::create(); // refCount = 2, , weakCount = 0, objPtr is created, then refCount = 1 because the return value is being destroyed
    std::weak_ptr<A> weakPtr1 = objPtr; // refCount = 2, weakCount = 1
    {
        std::shared_ptr<A> anotherPtr = objPtr; // refCount = 2, weakCount = 1
        {
            std::shared_ptr<A> yetAnotherPtr(anotherPtr); // refCount = 3, weakCount = 1
            std::weak_ptr<A> weakPtr2(anotherPtr); // refCount = 3, weakCount = 2
            // other stuff ......
        } // refCount = 2, yetAnotherPtr destructor is being called here; weakCount = 1 because weakPtr2 destructor is called
    } // refCount = 1, weakCount = 1, anotherPtr destructor is being called here
    return 0;
} // weakCount = 0, weakPtr1 destructor is called here
  // refCount = 0, objPtr destructor is being called here and finally internal
  // object being pointed is being deleted here
  • std::string
Sorry no time for this, come again later.
  • std::vector
Sorry no time for this, come again later.
  • STL
Sorry no time for this, come again later.
  • std::thread
In past C++(particularly) had many implementation of threads but that mainly depends upon the hardware and operating system. In C++11 we have a new standard library threads library, mainly a standard library ABI. 
Threads in C++11 are constructed using std::thread class which can be passed a function, function pointer etc or even a lambda.

void foo(const std::list<int>&);
struct Foo {
    std::list<int> list;
    Foo(const std::list<int>& l)
        : list(l)
    {
    }
    void operator()();
};
int main(int argc, const char * argv[])
{
    std::list<int> l1;
    std::list<int> l2;
    std::thread t1{std::bind(foo, l1)};// foo(l1) will run in a seprate thread
    std::thread t2{Foo(l2)}; // Foo(l2)() will run in a seprate thread
    std::thread t3([](){}); // lambda will run in a seprate thread
    t1.join(); // wait for t1 to complete
    t2.join(); // wait for t2 to complete
    t3.join(); // wait for t3 to complete
    return 0;
}
Calling join method on a thread gives us guarantee that the process does not terminates until the thread finishes execution. std::thread class has a method native_handle() that will return std::native_handle_type which maps to the native implementation defined thread handler. On a POSIX machine std::native_handle_type will map to pthread_t.
  • std::mutex
A mutex can be termed as a primitive object that is used for controlling the access to shared data in a muti-threaded environment. When a thread has to operate on a shared data it must acquire lock on the mutex and when it done with it it must unlock mutex.

#include <mutex>
static int shared = 0;
static std::mutex mutex;
void foo()
{
    mutex.lock();
    ++shared;
    mutex.unlock();
}
The code between lock() and unlock() is called critical region. It is general rule that critical region should be short enough. Only one of the thread at a time can operate in critical region, if another thread tries to enter into critical region it must first acquire lock on mutex, and second thread is blocked after call to lock() until fist thread leaves its critical region and calls union() on mutex.

There are other problems that may arise when programming in a multi-threaded environment. I will talk on the problems and how language support to avoid these problems some time later.
  • std::guard_lock and std::mutex
A lock is an object that maintains a reference to a mutex and calls mutex lock in its constructor and calls unlock in its destructor.

#include <mutex>
static int shared = 0;
static std::mutex mutex;
void foo()
{
    std::lock_guard<std::mutex> mutexLocker(mutex);
    ++shared;
}
  • std::async
Sorry no time for this, come again later.
  • std::future and std::promise
Sorry no time for this, come again later.

For C++11 features support for Clang(click here) , gcc(click here) and Microsoft Visual studio(click here).

No comments:

Post a Comment