Template in c++

Function templates

template <class myType>
myType GetMax (myType a, myType b) {
 return (a>b?a:b);
}
int x,y;
GetMax <int> (x,y);
#include <iostream>
using namespace std;

template <class T>
T GetMax (T a, T b) {
  T result;
  result = (a>b)? a : b;
  return (result);
}

int main () {
  int i=5, j=6, k;
  long l=10, m=5, n;
  k=GetMax<int>(i,j);
  n=GetMax<long>(l,m);
  cout << k << endl;
  cout << n << endl;
  return 0;
}

Class templates

#include <iostream>
using namespace std;

template <class T>
class mypair {
    T a, b;
  public:
    mypair (T first, T second)
      {a=first; b=second;}
    T getmax ();
};

template <class T>
T mypair<T>::getmax ()
{
  T retval;
  retval = a>b? a : b;
  return retval;
}

int main () {
  mypair <int> myobject (100, 75);
  cout << myobject.getmax();
  return 0;
}
#include <iostream>
using namespace std;

// class template:
template <class T>
class mycontainer {
    T element;
  public:
    mycontainer (T arg) {element=arg;}
    T increase () {return ++element;}
};

// class template specialization:
template <>
class mycontainer <char> {
    char element;
  public:
    mycontainer (char arg) {element=arg;}
    char uppercase ()
    {
      if ((element>='a')&&(element<='z'))
      element+='A'-'a';
      return element;
    }
};

int main () {
  mycontainer<int> myint (7);
  mycontainer<char> mychar ('j');
  cout << myint.increase() << endl;
  cout << mychar.uppercase() << endl;
  return 0;
}
template <class T>
struct A{
    template<class AA>
    void fun();
};

template <class T>
template<class AA>
void A<T>::fun(){

}
template <>
template<>
void A<QString>::fun<QString>(){

}

template<>
struct A<int>{
    void fun();
};
void A<int>::fun(){

}

Non-type parameters for templates

#include <iostream>
using namespace std;

template <class T, int N>
class mysequence {
    T memblock [N];
  public:
    void setmember (int x, T value);
    T getmember (int x);
};

template <class T, int N>
void mysequence<T,N>::setmember (int x, T value) {
  memblock[x]=value;
}

template <class T, int N>
T mysequence<T,N>::getmember (int x) {
  return memblock[x];
}

int main () {
  mysequence <int,5> myints;
  mysequence <double,5> myfloats;
  myints.setmember (0,100);
  myfloats.setmember (3,3.1416);
  cout << myints.getmember(0) << '\n';
  cout << myfloats.getmember(3) << '\n';
  return 0;
}

Parameter pack or Variadics template

template<class ... Types> void f(Types ... args);
f();       // OK: args contains no arguments
f(1);      // OK: args contains one argument: int
f(2, 1.0); // OK: args contains two arguments: int and double
template<typename... Ts, typename U> struct Invalid; // Error: Ts.. not at the end
 
template<typename ...Ts, typename U, typename=void>
void valid(U, Ts...);     // OK: can deduce U
// void valid(Ts..., U);  // Can't be used: Ts... is a non-deduced context in this position
 
valid(1.0, 1, 2, 3);      // OK: deduces U as double, Ts as {int,int,int}

Pack expansion

template<class ...Us> void f(Us... pargs) {}
template<class ...Ts> void g(Ts... args) {
    f(&args...); // “&args...” is a pack expansion
                 // “&args” is its pattern
}
g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3
                // &args... expands to &E1, &E2, &E3
                // Us... pargs expand to int* E1, double* E2, const char** E3
// The base case: we just have a single number.
template <typename T>
double sum(T t) {
    cout<<"call base sum\n";// call once at the last of recursion
    return t;
}

// The recursive case: we take a number, alongside
// some other numbers, and produce their sum.
template <typename T, typename... Rest>
double sum(T t, Rest... rest) {
    cout<<"call main sum\n";//call first 3 times
    return t + sum(rest...);
}

int main(int argc,char* argv[]){
    cout<<sum(1,2,3,4);//10
    return 0;
}

Template Specialize style


template <class T,class ...TT>
class AA;
template <class T,class ...TT>
class AA<T(TT...)>{
};

Class in c++ part2

abstract class

struct Base { virtual int g(); virtual ~Base() {} };
struct A : Base {
    // OK: declares three member virtual functions, two of them pure
    virtual int f() = 0, g() override = 0, h();
    // OK: destructor can be pure too
    ~A() = 0;
    // Error: pure-specifier on a function definition
    virtual int b()=0 {}
};
struct Abstract {
    virtual void f() = 0; // pure virtual
    virtual void g() {}  // non-pure virtual
    ~Abstract() {
        g(); // OK: calls Abstract::g()
        // f(); // undefined behavior
        Abstract::f(); // OK: non-virtual call
    }
};
 
// definition of the pure virtual function
void Abstract::f() { std::cout << "A::f()\n"; }
 
struct Concrete : Abstract {
    void f() override {
        Abstract::f(); // OK: calls pure virtual function
    }
    void g() override {}
    ~Concrete() {
        g(); // OK: calls Concrete::g()
        f(); // OK: calls Concrete::f()
    }
};

override specifier

struct A
{
    virtual void foo();
    void bar();
};
 
struct B : A
{
    void foo() const override; // Error: B::foo does not override A::foo
                               // (signature mismatch)
    void foo() override; // OK: B::foo overrides A::foo
    void bar() override; // Error: A::bar is not virtual
};

final specifier

struct Base
{
    virtual void foo();
};
 
struct A : Base
{
    void foo() final; // Base::foo is overridden and A::foo is the final override
    void bar() final; // Error: bar cannot be final as it is non-virtual
};
 
struct B final : A // struct B is final
{
    void foo() override; // Error: foo cannot be overridden as it is final in A
};
 
struct C : B // Error: B is final
{
};

friend declaration

class Y {
    int data; // private member
    // the non-member function operator<< will have access to Y's private members
    friend std::ostream& operator<<(std::ostream& out, const Y& o);
    friend char* X::foo(int); // members of other classes can be friends too
    friend X::X(char), X::~X(); // constructors and destructors can be friends
};
// friend declaration does not declare a member function
// this operator<< still needs to be defined, as a non-member
std::ostream& operator<<(std::ostream& out, const Y& y)
{
    return out << y.data; // can access private member Y::data
}
class F {};
int f();
int main()
{
    extern int g();
    class Local { // Local class in the main() function
        friend int f(); // Error, no such function declared in main()
        friend int g(); // OK, there is a declaration for g in main()
        friend class F; // friends a local F (defined later)
        friend class ::F; // friends the global F
    };
    class F {}; // local F
}

Bit field

#include <iostream>
struct S {
    // will usually occupy 2 bytes:
    // 3 bits: value of b1
    // 2 bits: unused
    // 6 bits: value of b2
    // 2 bits: value of b3
    // 3 bits: unused
    unsigned char b1 : 3, : 2, b2 : 6, b3 : 2;
};
int main()
{
    std::cout << sizeof(S) << '\n'; // usually prints 2
}
#include <iostream>
struct S {
    // will usually occupy 2 bytes:
    // 3 bits: value of b1
    // 5 bits: unused
    // 6 bits: value of b2
    // 2 bits: value of b3
    unsigned char b1 : 3;
    unsigned char :0; // start a new byte
    unsigned char b2 : 6;
    unsigned char b3 : 2;
};
int main()
{
    std::cout << sizeof(S) << '\n'; // usually prints 2
}

If the specified size of the bit field is greater than the size of its type, the value is limited by the type: a std::uint8_t b : 1000; would still hold values between 0 and 255. the extra bits become unused padding.

This Pointer

class T
{
    int x;
 
    void foo()
    {
        x = 6;       // same as this->x = 6;
        this->x = 5; // explicit use of this->
    }
 
    void foo() const
    {
//        x = 7; // Error: *this is constant
    }
 
    void foo(int x) // parameter x shadows the member with the same name
    {
        this->x = x; // unqualified x refers to the parameter
                     // 'this->' required for disambiguation
    }
 
    int y;
    T(int x) : x(x), // uses parameter x to initialize member x
               y(this->x) // uses member x to initialize member y
    {}
 
    T& operator= ( const T& b )
    {
        x = b.x;
        return *this; // many overloaded operators return *this
    }
};
 
class Outer {
    int a[sizeof(*this)]; // error: not inside a member function
    unsigned int sz = sizeof(*this); // OK: in default member initializer
    void f() {
        int b[sizeof(*this)]; // OK
        struct Inner {
            int c[sizeof(*this)]; // error: not inside a member function of Inner
        };
    }
}

Constructors and member initializer lists

#include <fstream>
#include <string>
#include <mutex>
 
struct Base {
    int n;
};   
 
struct Class : public Base
{
    unsigned char x;
    unsigned char y;
    std::mutex m;
    std::lock_guard<std::mutex> lg;
    std::fstream f;
    std::string s;
 
    Class ( int x )
      : Base { 123 }, // initialize base class
        x ( x ),      // x (member) is initialized with x (parameter)
        y { 0 },      // y initialized to 0
        f{"test.cc", std::ios::app}, // this takes place after m and lg are initialized
        s(__func__),   //__func__ is available because init-list is a part of constructor
        lg ( m ),      // lg uses m, which is already initialized
        m{}            // m is initialized before lg even though it appears last here
    {}                // empty compound statement
 
    Class ( double a )
      : y ( a+1 ),
        x ( y ), // x will be initialized before y, its value here is indeterminate
        lg ( m )
    {} // base class initializer does not appear in the list, it is
       // default-initialized (not the same as if Base() were used, which is value-init)
 
    Class()
    try // function-try block begins before the function body, which includes init list
      : Class( 0.0 ) //delegate constructor
    {
        // ...
    }
    catch (...)
    {
        // exception occurred on initialization
    }
};
 
int main() {
    Class c;
    Class c1(1);
    Class c2(0.1);
}

Default constructors

struct A
{
    int x;
    A(int x = 1): x(x) {} // user-defined default constructor
};
 
struct B: A
{
    // B::B() is implicitly-defined, calls A::A()
};
 
struct C
{
    A a;
    // C::C() is implicitly-defined, calls A::A()
};
 
struct D: A
{
    D(int y): A(y) {}
    // D::D() is not declared because another constructor exists
};
 
struct E: A
{
    E(int y): A(y) {}
    E() = default; // explicitly defaulted, calls A::A()
};
 
struct F
{
    int& ref; // reference member
    const int c; // const member
    // F::F() is implicitly defined as deleted
};
 
int main()
{
    A a;
    B b;
    C c;
//  D d; // compile error
    E e;
//  F f; // compile error
}

Destructor

#include <iostream>
 
struct A
{
    int i;
 
    A ( int i ) : i ( i ) 
    {
        std::cout << "ctor a" << i << '\n';
    }
 
    ~A()
    {
        std::cout << "dtor a" << i << '\n';
    }
};
 
A a0(0);
 
int main()
{
    A a1(1);
    A* p;
 
    { // nested scope
        A a2(2);
        p = new A(3);
    } // a2 out of scope
 
    delete p; // calls the destructor of a3
}

Copy constructors

struct A
{
    int n;
    A(int n = 1) : n(n) { }
    A(const A& a) : n(a.n) { } // user-defined copy ctor
};
 
struct B : A
{
    // implicit default ctor B::B()
    // implicit copy ctor B::B(const B&)
};
 
struct C : B
{
     C() : B() { }
 private:
     C(const C&); // non-copyable, C++98 style
};
 
int main()
{
    A a1(7);
    A a2(a1); // calls the copy ctor
    B b;
    B b2 = b;
    A a3 = b; // conversion to A& and copy ctor
    volatile A va(10);
    // A a4 = va; // compile error
 
    C c;
    // C c2 = c; // compile error
}

Copy assignment operator

#include <iostream>
#include <memory>
#include <string>
#include <algorithm>
 
struct A
{
    int n;
    std::string s1;
    // user-defined copy assignment, copy-and-swap form
    A& operator=(A other)
    {
        std::cout << "copy assignment of A\n";
        std::swap(n, other.n);
        std::swap(s1, other.s1);
        return *this;
    }
};
 
struct B : A
{
    std::string s2;
    // implicitly-defined copy assignment
};
 
struct C
{
    std::unique_ptr<int[]> data;
    std::size_t size;
    // non-copy-and-swap assignment
    C& operator=(const C& other)
    {
        // check for self-assignment
        if(&other == this)
            return *this;
        // reuse storage when possible
        if(size != other.size)
        {
            data.reset(new int[other.size]);
            size = other.size;
        }
        std::copy(&other.data[0], &other.data[0] + size, &data[0]);
        return *this;
    }
    // note: copy-and-swap would always cause a reallocation
};
 
int main()
{
    A a1, a2;
    std::cout << "a1 = a2 calls ";
    a1 = a2; // user-defined copy assignment
 
    B b1, b2;
    b2.s1 = "foo";
    b2.s2 = "bar";
    std::cout << "b1 = b2 calls ";
    b1 = b2; // implicitly-defined copy assignment
    std::cout << "b1.s1 = " << b1.s1 << " b1.s2 = " << b1.s2 << '\n';
}

Move constructors

#include <string>
#include <iostream>
#include <iomanip>
#include <utility>
 
struct A
{
    std::string s;
    int k;
    A() : s("test"), k(-1) { }
    A(const A& o) : s(o.s), k(o.k) { std::cout << "move failed!\n"; }
    A(A&& o) noexcept :
           s(std::move(o.s)),       // explicit move of a member of class type
           k(std::exchange(o.k, 0)) // explicit move of a member of non-class type
    { }
};
 
A f(A a)
{
    return a;
}
 
struct B : A
{
    std::string s2;
    int n;
    // implicit move constructor B::(B&&)
    // calls A's move constructor
    // calls s2's move constructor
    // and makes a bitwise copy of n
};
 
struct C : B
{
    ~C() { } // destructor prevents implicit move constructor C::(C&&)
};
 
struct D : B
{
    D() { }
    ~D() { }          // destructor would prevent implicit move constructor D::(D&&)
    D(D&&) = default; // forces a move constructor anyway
};
 
int main()
{
    std::cout << "Trying to move A\n";
    A a1 = f(A()); // return by value move-constructs the target from the function parameter
    std::cout << "Before move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n';
    A a2 = std::move(a1); // move-constructs from xvalue
    std::cout << "After move, a1.s = " << std::quoted(a1.s) << " a1.k = " << a1.k << '\n';
 
    std::cout << "Trying to move B\n";
    B b1;
    std::cout << "Before move, b1.s = " << std::quoted(b1.s) << "\n";
    B b2 = std::move(b1); // calls implicit move constructor
    std::cout << "After move, b1.s = " << std::quoted(b1.s) << "\n";
 
    std::cout << "Trying to move C\n";
    C c1;
    C c2 = std::move(c1); // calls copy constructor
 
    std::cout << "Trying to move D\n";
    D d1;
    D d2 = std::move(d1);
}

Move assignment operator

#include <string>
#include <iostream>
#include <utility>
 
struct A
{
    std::string s;
    A() : s("test") { }
    A(const A& o) : s(o.s) { std::cout << "move failed!\n"; }
    A(A&& o) : s(std::move(o.s)) { }
    A& operator=(const A& other)
    {
         s = other.s;
         std::cout << "copy assigned\n";
         return *this;
    }
    A& operator=(A&& other)
    {
         s = std::move(other.s);
         std::cout << "move assigned\n";
         return *this;
    }
};
 
A f(A a) { return a; }
 
struct B : A
{
     std::string s2; 
     int n;
     // implicit move assignment operator B& B::operator=(B&&)
     // calls A's move assignment operator
     // calls s2's move assignment operator
     // and makes a bitwise copy of n
};
 
struct C : B
{
    ~C() { } // destructor prevents implicit move assignment
};
 
struct D : B
{
    D() { }
    ~D() { } // destructor would prevent implicit move assignment
    D& operator=(D&&) = default; // force a move assignment anyway 
};
 
int main()
{
    A a1, a2;
    std::cout << "Trying to move-assign A from rvalue temporary\n";
    a1 = f(A()); // move-assignment from rvalue temporary
    std::cout << "Trying to move-assign A from xvalue\n";
    a2 = std::move(a1); // move-assignment from xvalue
 
    std::cout << "Trying to move-assign B\n";
    B b1, b2;
    std::cout << "Before move, b1.s = \"" << b1.s << "\"\n";
    b2 = std::move(b1); // calls implicit move assignment
    std::cout << "After move, b1.s = \"" << b1.s << "\"\n";
 
    std::cout << "Trying to move-assign C\n";
    C c1, c2;
    c2 = std::move(c1); // calls the copy assignment operator
 
    std::cout << "Trying to move-assign D\n";
    D d1, d2;
    d2 = std::move(d1);
}

Converting constructor

struct A
{
    A() { }         // converting constructor (since C++11)  
    A(int) { }      // converting constructor
    A(int, int) { } // converting constructor (since C++11)
};
 
struct B
{
    explicit B() { }
    explicit B(int) { }
    explicit B(int, int) { }
};
 
int main()
{
    A a1 = 1;      // OK: copy-initialization selects A::A(int)
    A a2(2);       // OK: direct-initialization selects A::A(int)
    A a3{4, 5};    // OK: direct-list-initialization selects A::A(int, int)
    A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
    A a5 = (A)1;   // OK: explicit cast performs static_cast, direct-initialization
 
//  B b1 = 1;      // error: copy-initialization does not consider B::B(int)
    B b2(2);       // OK: direct-initialization selects B::B(int)
    B b3{4, 5};    // OK: direct-list-initialization selects B::B(int, int)
//  B b4 = {4, 5}; // error: copy-list-initialization selected an explicit constructor
                   //        B::B(int, int)
    B b5 = (B)1;   // OK: explicit cast performs static_cast, direct-initialization
    B b6;          // OK, default-initialization
    B b7{};        // OK, direct-list-initialization
//  B b8 = {};     // error: copy-list-initialization selected an explicit constructor
                   //        B::B()
}

lvalue and rvalue functions

class A{
public:
    void fun()&{
        cout<<"can called only by lvalue";
    }
    void fun()&&{
        cout<<"can called only by rvalue";
    }
};

Classes in c++ part 1

Class declaration

Member specification

class S {
    int d1; // non-static data member
    int a[10] = {1,2}; // non-static data member with initializer (C++11)
    static const int d2 = 1; // static data member with initializer
    virtual void f1(int) = 0; // pure virtual member function
    std::string d3, *d4, f2(int); // two data members and a member function
    enum {NORTH, SOUTH, EAST, WEST};
    struct NestedS {
        std::string s;
    } d5, *d6;
    typedef NestedS value_type, *pointer_type;
}

Function definitions

class M {
    std::size_t C;
    std::vector<int> data;
 public:
    M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition 
    int operator()(size_t r, size_t c) const { // member function definition
        return data[r*C+c];
    }
    int& operator()(size_t r, size_t c) {  // another member function definition
        return data[r*C+c];
    }
};

 Access specifiers

class S {
 public:
    S();          // public constructor
    S(const S&);  // public copy constructor
    virtual ~S(); // public virtual destructor
 private:
    int* ptr; // private data member
};

Using-declarations

class Base {
 protected:
     int d;
};
class Derived : public Base {
 public:
    using Base::d; // make Base's protected member d a public member of Derived
    using Base::Base; // inherit all parent's constructors (C++11)
};

member template declarations

struct S {
    template<typename T>
    void f(T&& n);
 
    template<class CharT>
    struct NestedS {
        std::basic_string<CharT> s;
    };
};

alias declarations

template <typename T>
struct identity
{
    using type = T;
};

local struct

 
int main()
{
    std::vector<int> v{1,2,3};
    struct Local {
       bool operator()(int n, int m) {
           return n > m;
       }
    };
    std::sort(v.begin(), v.end(), Local()); // since C++11
    for(int n: v) std::cout << n << ' ';
}

injected-class-name

int X;
struct X {
    void f() {
        X* p; // OK. X refers to the injected-class-name
        ::X* q; // Error: name lookup finds a variable name, which hides the struct name
    }
};
struct A {
    A();
    A(int);
    template<class T> A(T) {}
};
using A_alias = A;
 
A::A() {}
A_alias::A(int) {}
template A::A(double);
 
struct B : A {
    using A_alias::A;
};
 
A::A a; // Error: A::A is considered to name a constructor, not a type
struct A::A a2; // OK, same as 'A a2;'
B::A b; // OK, same as 'A b;'

Non-static data members

struct A { int a; char b; };
struct B { const int b1; volatile char b2; }; 
// A and B's common initial sequence is A.a, A.b and B.b1, B.b2
struct C { int c; unsigned : 0; char b; };
// A and C's common initial sequence is A.a and C.c
struct D { int d; char b : 4; };
// A and D's common initial sequence is A.a and D.d
struct E { unsigned int e; char b; };
// A and E's common initial sequence is empty

Member initialization

struct S
{
    int n;
    std::string s;
    S() : n(7) // direct-initializes n, default-initializes s
    { }
};
int x = 0;
struct S
{
    int n = ++x;
    S() { }                 // uses default member initializer
    S(int arg) : n(arg) { } // uses member initializer 
};
 
int main()
{
    std::cout << x << '\n'; // prints 0
    S s1;
    std::cout << x << '\n'; // prints 1 (default initializer ran)
    S s2(7);
    std::cout << x << '\n'; // prints 1 (default initializer did not run)
}
struct X {
   int a[] = {1,2,3}; // error
   int b[3] = {1,2,3}; // OK
};
struct node {
    node* p = new node; // error: use of implicit or defaulted node::node() 
};
struct A
{
    A() = default;          // OK
    A(int v) : v(v) { }     // OK
    const int& v = 42;      // OK
};
A a1;    // error: ill-formed binding of temporary to reference
A a2(1); // OK (default member initializer ignored because v appears in a constructor)
         // however a2.v is a dangling reference
struct S
{
    int m;
    int n;
    int x = m;            // OK: implicit this-> allowed in default initializers (C++11)
    S(int i) : m(i), n(m) // OK: implicit this-> allowed in member initializer lists
    {
        this->f();        // explicit member access expression
        f();              // implicit this-> allowed in member function bodies
    }
    void f();
};
struct S
{
   int m;
   void f();
};
int S::*p = &S::m;       // OK: use of m to make a pointer to member
void (S::*fp)() = &S::f; // OK: use of f to make a pointer to member

Non-static member functions

#include <iostream>
#include <string>
#include <utility>
#include <exception>
 
struct S {
    int data;
 
    // simple converting constructor (declaration)
    S(int val);
 
    // simple explicit constructor (declaration)
    explicit S(std::string str);
 
    // const member function (definition)
    virtual int getData() const { return data; }
 
};
 
// definition of the constructor
S::S(int val) : data(val) {
    std::cout << "ctor1 called, data = " << data << '\n';
}
 
// this constructor has a catch clause
S::S(std::string str) try : data(std::stoi(str)) {
    std::cout << "ctor2 called, data = " << data << '\n';
} catch(const std::exception&) {
    std::cout << "ctor2 failed, string was '" << str << "'\n";
    throw; // ctor's catch clause should always rethrow
}
 
struct D : S {
    int data2;
    // constructor with a default argument
    D(int v1, int v2 = 11) : S(v1), data2(v2) {}
 
    // virtual member function
    int getData() const override { return data*data2; }
 
    // lvalue-only assignment operator
    D& operator=(D other) & {
        std::swap(other.data, data);
        std::swap(other.data2, data2);
        return *this;
    }
};
 
int main()
{
    D d1 = 1;
    S s2("2");
    try {
         S s3("not a number");
    } catch(const std::exception&) {}
    std::cout << s2.getData() << '\n';
 
   D d2(3, 4);
   d2 = d1; // OK: assignment to lvalue
//   D(5) = d1; // ERROR: no suitable overload of operator=
}

nested classes

struct enclose {
    struct inner {
        static int x;
        void f(int i);
    };
};
int enclose::inner::x = 1; // definition
void enclose::inner::f(int i) {} // definition
class enclose {
    class nested1; // forward declaration
    class nested2; // forward declaration
    class nested1 {}; // definition of nested class
};
class enclose::nested2 { }; // definition of nested class
class enclose {
    struct nested { // private member
        void g() {}
    };
 public:
    static nested f() { return nested{}; }
};
 
int main()
{
    //enclose::nested n1 = enclose::f(); // error: 'nested' is private
 
    enclose::f().g(); // OK: does not name 'nested'
    auto n2 = enclose::f(); // OK: does not name 'nested'
    n2.g();
}

Derived classes

Virtual base classes

struct B { int n; };
class X : public virtual B {};
class Y : virtual public B {};
class Z : public B {};
// every object of type AA has one X, one Y, one Z, and two B's:
// one that is the base of Z and one that is shared by X and Y
struct AA : X, Y, Z {
    AA() {
        X::n = 1; // modifies the virtual B subobject's member
        Y::n = 2; // modifies the same virtual B subobject's member
        Z::n = 3; // modifies the non-virtual B subobject's member
 
        std::cout << X::n << Y::n << Z::n << '\n'; // prints 223
    }
};
struct B {
    int n;
    B(int x) : n(x) {}
};
struct X : virtual B { X() : B(1) {} };
struct Y : virtual B { Y() : B(2) {} };
struct AA : X, Y     { AA() : B(3), X(), Y() {} };
 
// the default constructor of AA calls the default constructors of B , X and Y 
// but those constructors do not call the constructor of B because B is a virtual base
AA a; // a.n == 3
// the default constructor of X calls the constructor of B
X x; // x.n == 1
class A{
public:
    A(){
       cout<<"call A\n";
    }
};

class B:virtual public A{
public:
    B(){
        cout<<"call B\n";
    }
};

class C:virtual public A{
public:
    C(){
        cout<<"call C\n";
    }
};

class D: public B,public C{
public:
    D(){
        cout<<"call D\n";
    }
};



int main()
{
    D b;
}

output
call A
call B
call C
call D
without virtual
output
call A
call B
call A
call C
call D

Using-declaration

#include <iostream>
struct B {
    virtual void f(int) { std::cout << "B::f\n"; }
    void g(char)        { std::cout << "B::g\n"; }
    void h(int)         { std::cout << "B::h\n"; }
 protected:
    int m; // B::m is protected
    typedef int value_type;
};
 
struct D : B {
    using B::m; // D::m is public
    using B::value_type; // D::value_type is public
 
    using B::f;
    void f(int) { std::cout << "D::f\n"; } // D::f(int) overrides B::f(int)
    using B::g;
    void g(int) { std::cout << "D::g\n"; } // both g(int) and g(char) are visible
                                           // as members of D
    using B::h;
    void h(int) { std::cout << "D::h\n"; } // D::h(int) hides B::h(int)
};
 
int main()
{
    D d;
    B& b = d;
 
//    b.m = 2; // error, B::m is protected
    d.m = 1; // protected B::m is accessible as public D::m
    b.f(1); // calls derived f()
    d.f(1); // calls derived f()
    d.g(1); // calls derived g(int)
    d.g('a'); // calls base g(char)
    b.h(1); // calls base h()
    d.h(1); // calls derived h()
}
struct B1 {  B1(int, ...) { } };
struct B2 {  B2(double)   { } };
 
int get();
 
struct D1 : B1 {
  using B1::B1;  // inherits B1(int, ...)
  int x;
  int y = get();
};
 
void test() {
  D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
                 // then d.x is default-initialized (no initialization is performed),
                 // then d.y is initialized by calling get()
  D1 e;          // Error: D1 has no default constructor
}
 
struct D2 : B2 {
  using B2::B2; // inherits B2(double)
  B1 b;
};
 
D2 f(1.0);       // error: B1 has no default constructor
struct A { A(int); };
struct B : A { using A::A; };
struct C1 : B { using B::B; };
struct C2 : B { using B::B; };
 
struct D1 : C1, C2 {
  using C1::C1;
  using C2::C2;
};
D1 d1(0); // ill-formed: constructor inherited from different B base subobjects
 
struct V1 : virtual B { using B::B; };
struct V2 : virtual B { using B::B; };
 
struct D2 : V1, V2 {
  using V1::V1;
  using V2::V2;
};
D2 d2(0); // OK: there is only one B subobject.
          // This initializes the virtual B base class,
          //  which initializes the A base class
          // then initializes the V1 and V2 base classes
          //  as if by a defaulted default constructor

virtual function specifier

struct A { virtual void f(); };     // A::f is virtual
struct B : A { void f(); };         // B::f overrides A::f in B
struct C : virtual B { void f(); }; // C::f overrides A::f in C
struct D : virtual B {}; // D does not introduce an overrider, B::f is final in D
struct E : C, D  {       // E does not introduce an overrider, C::f is final in E
    using A::f; // not a function declaration, just makes A::f visible to lookup
};
int main() {
   E e;
   e.f();    // virtual call calls C::f, the final overrider in e
   e.E::f(); // non-virtual call calls A::f, which is visible in E
}
class B {
    virtual void do_f(); // private member
 public:
    void f() { do_f(); } // public interface
};
struct D : public B {
    void do_f() override; // overrides B::do_f
};
 
int main()
{
    D d;
    B* bp = &d;
    bp->f(); // internally calls D::do_f();
}

Virtual destructor

class Base {
 public:
    virtual ~Base() { /* releases Base's resources */ }
};
 
class Derived : public Base {
    ~Derived() { /* releases Derived's resources */ }
};
 
int main()
{
    Base* b = new Derived;
    delete b; // Makes a virtual function call to Base::~Base()
              // since it is virtual, it calls Derived::~Derived() which can
              // release resources of the derived class, and then calls
              // Base::~Base() following the usual order of destruction
}

Covariant return types

class B {};
 
struct Base {
    virtual void vf1();
    virtual void vf2();
    virtual void vf3();
    virtual B* vf4();
    virtual B* vf5();
};
 
class D : private B {
    friend struct Derived; // in Derived, B is an accessible base of D
};
 
class A; // forward-declared class is an incomplete type
 
struct Derived : public Base {
    void vf1();    // virtual, overrides Base::vf1()
    void vf2(int); // non-virtual, hides Base::vf2()
//  char vf3();    // Error: overrides Base::vf3, but has different
                   // and non-covariant return type
    D* vf4();      // overrides Base::vf4() and has covariant return type
//  A* vf5();      // Error: A is incomplete type
};
 
int main()
{
    Derived d;
    Base& br = d;
    Derived& dr = d;
 
    br.vf1(); // calls Derived::vf1()
    br.vf2(); // calls Base::vf2()
//  dr.vf2(); // Error: vf2(int) hides vf2()
 
    B* p = br.vf4(); // calls Derived::vf4() and converts the result to B*
    D* q = dr.vf4(); // calls Derived::vf4() and does not convert
                     //  the result to B*
 
}

initialization in c++

Default initialization

struct T1 { int mem; };
 
struct T2
{
    int mem;
    T2() { } // "mem" is not in the initializer list
};
 
int n; // static non-class, a two-phase initialization is done:
       // 1) zero initialization initializes n to zero
       // 2) default initialization does nothing, leaving n being zero
 
int main()
{
    int n;            // non-class, the value is indeterminate
    std::string s;    // class, calls default ctor, the value is "" (empty string)
    std::string a[2]; // array, default-initializes the elements, the value is {"", ""}
//  int& r;           // error: a reference
//  const int n;      // error: a const non-class
//  const T1 t1;      // error: const class with implicit default ctor
    T1 t1;            // class, calls implicit default ctor
    const T2 t2;      // const class, calls the user-provided default ctor
                      // t2.mem is default-initialized (to indeterminate value)
}

Value initialization

T()
new T ()
Class::Class() : member() {  }
T object {};
T{}
new T {}
Class::Class() : member{} {  }

struct T1
{
    int mem1;
    std::string mem2;
}; // implicit default constructor
 
struct T2
{
    int mem1;
    std::string mem2;
    T2(const T2&) { } // user-provided copy constructor
};                    // no default constructor
 
struct T3
{
    int mem1;
    std::string mem2;
    T3() { } // user-provided default constructor
};
 
std::string s{}; // class => default-initialization, the value is ""
 
int main()
{
    int n{};                // scalar => zero-initialization, the value is 0
    double f = double();    // scalar => zero-initialization, the value is 0.0
    int* a = new int[10](); // array => value-initialization of each element
                            //          the value of each element is 0
    T1 t1{};                // class with implicit default constructor =>
                            //     t1.mem1 is zero-initialized, the value is 0
                            //     t1.mem2 is default-initialized, the value is ""
//  T2 t2{};                // error: class with no default constructor
    T3 t3{};                // class with user-provided default constructor =>
                            //     t3.mem1 is default-initialized to indeterminate value
                            //     t3.mem2 is default-initialized, the value is ""
    std::vector<int> v(3);  // value-initialization of each element
                            // the value of each element is 0
    std::cout << s.size() << ' ' << n << ' ' << f << ' ' << a[9] << ' ' << v[2] << '\n';
    std::cout << t1.mem1 << ' ' << t3.mem1 << '\n';
    delete[] a;
}

Direct initialization

T object arg );
T object arg1, arg2, … );
T object arg };
T other )
T arg1, arg2, … )
static_cast< T >( other )
new T(args, …)
Class::Class() : member(args, …) {  }
[arg](){  }
struct B {
  int a;
  int&& r;
};
 
int f();
int n = 10;
 
B b1{1, f()};               // OK, lifetime is extended
B b2(1, f());               // well-formed, but dangling reference
B b3{1.0, 1};               // error: narrowing conversion
B b4(1.0, 1);               // well-formed, but dangling reference
B b5(1.0, std::move(n));    // OK
struct M { };
struct L { L(M&); };
 
M n;
void f() {
    M(m); // declaration, equivalent to M m;
    L(n); // ill-formed declaration
    L(l)(m); // still a declaration
}

Copy initialization

T object = other;
T object = {other;
f(other)
return other;
throw object;catch (T object)
T array[N] = {other};
struct A 
{
  operator int() { return 12;}
};
 
struct B 
{
  B(int) {}
};
 
int main()
{
    std::string s = "test"; // OK: constructor is non-explicit
    std::string s2 = std::move(s); // this copy-initialization performs a move
 
//  std::unique_ptr<int> p = new int(1); // error: constructor is explicit
    std::unique_ptr<int> p(new int(1)); // OK: direct-initialization
 
 
    int n = 3.14;    // floating-integral conversion
    const int b = n; // const doesn't matter
    int c = b;       // ...either way
 
 
    A a;
    B b0 = 12;
//    B b1 = a; //< error: conversion from 'A' to non-scalar type 'B' requested
    B b2{a};        // < identical, calling A::operator int(), then B::B(int)
    B b3 = {a};     // <
    auto b4 = B{a}; // <
 
//    b0 = a; //< error, assignment operator overload needed 
}

Aggregate initialization

T object = {arg1, arg2, …};
T object {arg1, arg2, …};
T object = { .designator = arg1 , .designator { arg2 } … };
T object { .designator = arg1 , .designator { arg2 } … };
T object (arg1, arg2, …);
struct A { int x; int y; int z; };
A a{.y = 2, .x = 1}; // error; designator order does not match declaration order
A b{.x = 1, .z = 2}; // ok, b.y initialized to 0
union u { int a; const char* b; };
u f = { .b = "asdf" };         // OK, active member of the union is b
u g = { .a = 1, .b = "asdf" }; // Error, only one initializer may be provided
struct A { int x, y; };
struct B { struct A a; };
struct A a = {.y = 1, .x = 2}; // valid C, invalid C++ (out of order)
int arr[3] = {[1] = 5};        // valid C, invalid C++ (array)
struct B b = {.a.x = 0};       // valid C, invalid C++ (nested)
struct A a = {.x = 1, 2};      // valid C, invalid C++ (mixed)
char a[] = "abc";
// equivalent to char a[4] = {'a', 'b', 'c', '\0'};
 
//  unsigned char b[3] = "abc"; // Error: initializer string too long
unsigned char b[5]{"abc"};
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '\0', '\0'};
 
wchar_t c[] = {L"кошка"}; // optional braces
// equivalent to wchar_t c[6] = {L'к', L'о', L'ш', L'к', L'а', L'\0'};
struct S {
    int x;
    struct Foo {
        int i;
        int j;
        int a[3];
    } b;
};
 
union U {
    int a;
    const char* b;
};
 
int main()
{
    S s1 = { 1, { 2, 3, {4, 5, 6} } };
    S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
    S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax
    S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign
                            // okay in C++14
 
    int ar[] = {1,2,3}; // ar is int[3]
    int ab[] (1, 2, 3); // (C++20) ab is int[3] 
//  char cr[3] = {'a', 'b', 'c', 'd'}; // too many initializer clauses
    char cr[3] = {'a'}; // array initialized as {'a', '\0', '\0'}
 
    int ar2d1[2][2] = {{1, 2}, {3, 4}}; // fully-braced 2D array: {1, 2}
                                        //                        {3, 4}
    int ar2d2[2][2] = {1, 2, 3, 4}; // brace elision: {1, 2}
                                    //                {3, 4}
    int ar2d3[2][2] = {{1}, {2}};   // only first column: {1, 0}
                                    //                    {2, 0}
 
    std::array<int, 3> std_ar2{ {1,2,3} };    // std::array is an aggregate
    std::array<int, 3> std_ar1 = {1, 2, 3}; // brace-elision okay
 
    int ai[] = { 1, 2.0 }; // narrowing conversion from double to int:
                           // error in C++11, okay in C++03
 
    std::string ars[] = {std::string("one"), // copy-initialization
                         "two",              // conversion, then copy-initialization
                         {'t', 'h', 'r', 'e', 'e'} }; // list-initialization
 
    U u1 = {1}; // OK, first member of the union
//    U u2 = { 0, "asdf" }; // error: too many initializers for union
//    U u3 = { "asdf" }; // error: invalid conversion to int
 
}
 
// aggregate
struct base1 { int b1, b2 = 42; };
// non-aggregate
struct base2 {
  base2() : b3(42) {}
  int b3;
};
// aggregate in C++17
struct derived : base1, base2 { int d; };
derived d1{ {1, 2}, { }, 4}; // d1.b1 = 1, d1.b2 = 2,  d1.b3 = 42, d1.d = 4
derived d2{ {    }, { }, 4}; // d2.b1 = 0, d2.b2 = 42, d2.b3 = 42, d2.d = 4

List initialization

struct X {
    X() = default;
    X(const X&) = default;
};
 
struct Q {
    Q() = default;
    Q(Q const&) = default;
    Q(std::initializer_list<Q>) {}
};
 
int main() {
  X x;
  X x2 = X { x }; // copy-constructor (not aggregate initialization)
  Q q;
  Q q2 = Q { q }; // initializer-list constructor (not copy constructor)
}

Reference initialization

T & ref = object ;
T & ref = arg1, arg2, … };
T & ref ( object ) ;
T & ref arg1, arg2, … } ;
T && ref = object ;
T && ref = arg1, arg2, … };
T && ref ( object ) ;
T && ref { arg1, arg2, … } ;
given R fn ( T & arg ); 
or R fn ( T && arg );
fn ( object )fn ( { arg1, arg2, … } )
inside T & fn () or T && fn ()return object ;
given T & ref ; or T && ref ; inside the definition of Class Class::Class(…) : ref( object) {…}
struct S {
    int mi;
    const std::pair<int, int>& mp; // reference member
};
 
void foo(int) {}
 
struct A {};
 
struct B : A {
    int n;
    operator int&() { return n; }
};
 
B bar() { return B(); }
 
//int& bad_r;      // error: no initializer
extern int& ext_r; // OK
 
int main() {
//  Lvalues
    int n = 1;
    int& r1 = n;                    // lvalue reference to the object n
    const int& cr(n);               // reference can be more cv-qualified
    volatile int& cv{n};            // any initializer syntax can be used
    int& r2 = r1;                   // another lvalue reference to the object n
//  int& bad = cr;                  // error: less cv-qualified
    int& r3 = const_cast<int&>(cr); // const_cast is needed
 
    void (&rf)(int) = foo; // lvalue reference to function
    int ar[3];
    int (&ra)[3] = ar;     // lvalue reference to array
 
    B b;
    A& base_ref = b;        // reference to base subobject
    int& converted_ref = b; // reference to the result of a conversion
 
//  Rvalues
//  int& bad = 1;        // error: cannot bind lvalue ref to rvalue
    const int& cref = 1; // bound to rvalue
    int&& rref = 1;      // bound to rvalue
 
    const A& cref2 = bar(); // reference to A subobject of B temporary
    A&& rref2 = bar();      // same
 
    int&& xref = static_cast<int&&>(n); // bind directly to n
//  int&& copy_ref = n;                 // error: can't bind to an lvalue
    double&& copy_ref = n;              // bind to an rvalue temporary with value 1.0
 
//  Restrictions on temporary lifetimes
    std::ostream& buf_ref = std::ostringstream() << 'a'; // the ostringstream temporary
                      // was bound to the left operand of operator<<
                      // but its lifetime ended at the semicolon
                      // so buf_ref is a dangling reference
 
    S a {1, {2, 3} };         // temporary pair {2, 3} bound to the reference member
                              // a.mp and its lifetime is extended to match a
    S* p = new S{1, {2, 3} }; // temporary pair {2, 3} bound to the reference
                              // member p->mp, but its lifetime ended at the semicolon
                              // p->mp is a dangling reference
    delete p;
}

examples

struct A{
    A(int i){

    }
};
struct B{
    B(A a){

    }
};
struct C{
    C(B b){

    }
};
int main(int argc,char* argv[]){
    B b=(A)5;
    B bb(5);
    C c((A)5);
    return 0;
}

Functions in c++

Function Pointer

using namespace std;

int fun(){
    cout<<"call fun";
    return 0;
}
typedef int (*ff)();
using fu=ff;

int main(int _argc,char* _argv[]){
    int(*f)()=fun;
    f();
    (*f)();
    ff fff=(ff)fun;
    fu fu1=fun;
    fu1();
}
class A{
public:
    virtual int fun(){
        cout<<"A";
        return 0;
    }
};

class B:public A{
public:
    int fun() override {
        cout<<"B";
        return 0;
    }
};

typedef int(A::*f)();

int main(int _argc,char* _argv[]){
    f ff=&A::fun;
    A a{};
    B b{};
    (a.*ff)();//A
    (b.*ff)();//B
}
class A{
public:
    int fun(){
        cout<<"A";
        return 0;
    }
};

class B:public A{
public:
    int fun() {
        cout<<"B";
        return 0;
    }
};

typedef int(A::*f)();

int main(int _argc,char* _argv[]){
    f ff=f(&B::fun);
    A a{};
    B b{};
    (a.*ff)();//B
    (b.*ff)();//B
}

you can not cast non virtual function pointer

class Foo{
public:
  int f(char* c=0){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
class Bar{
public:
  void b(int i=0){
    std::cout<<"Bar::b()"<<std::endl;
  }
};
 
class FooDerived:public Foo{
public:
  int f(char* c=0){
    std::cout<<"FooDerived::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  typedef  int (Foo::*FPTR) (char*);
  typedef  void (Bar::*BPTR) (int);
  typedef  int (FooDerived::*FDPTR) (char*);
 
  FPTR fptr = &Foo::f;
  BPTR bptr = &Bar::b;
  FDPTR fdptr = &FooDerived::f;
 
  //Bptr = static_cast<void (Bar::*) (int)> (fptr); //error
  fdptr = static_cast<int (Foo::*) (char*)> (fptr); //OK: contravariance
 
  Bar obj;
  ( obj.*(BPTR) fptr )(1);//call: Foo::f()
}
Output:
Foo::f()

you can cast virtual function pointer

class Foo{
public:
  virtual int f(char* c=0){
    std::cout<<"Foo::f()"<<std::endl;
    return 1;
  }
};
 
class Bar{
public:
  virtual void b(int i=0){
    std::cout<<"Bar::b()"<<std::endl;
  }
};
 
class FooDerived:public Foo{
public:
  int f(char* c=0){
    std::cout<<"FooDerived::f()"<<std::endl;
    return 1;
  }
};
 
int main(int argc, char* argv[]){
  typedef  int (Foo::*FPTR) (char*);
  typedef  void (Bar::*BPTR) (int);
  FPTR fptr=&Foo::f;
  BPTR bptr=&Bar::b;
 
  FooDerived objDer;
  (objDer.*fptr)(0);//call: FooDerived::f(), not Foo::f()
 
  Bar obj;
  ( obj.*(BPTR) fptr )(1);//call: Bar::b() , not Foo::f()
}
Output:
FooDerived::f()
Bar::b()
class A{
public:
    void fun(){
        cout<<"A";
    }
};
class B:public A{
public:
    void fun(){
        cout<<"B";
    }
};
int main(int _argc,char* _argv[]){
    typedef void (A::*f)();
    f f1=(f)&B::fun;
    B b;
    (b.*f1)();// if B did not inherit A (b.*(void (B::*)())f1)();
}

generic function pointer

template<class T>
void fun(void(T::*f)(int)){
    T t;
    (t.*f)(12);
}

class A{
    public:
        void fun(int i){
            cout<<i;
        }
    };

int main(int argc,char* argv[]){
    fun(&A::fun);
    return 0;
}
template<int i,typename T>
 int iter(T t){
     return i-1;
 }

 template<typename T>
 struct A{
     T t;
 };

 template<typename T>
 using fun= int(*)(T t);

 template <typename T>
 using attr=T A<T>::*;


int main(int argc, char *argv[])
{
    QCoreApplication a(argc,argv);
    fun<int> f=iter<2,int>;
    attr<int> at=&A<int>::t;

    return a.exec();
}

lambda expression

[ captures ] ( params ) -> ret { body }
[ captures ] ( params ) { body }
[ captures ] { body }

[&]{};          // OK: by-reference capture default
[&, i]{};       // OK: by-reference capture, except i is captured by copy
[&, &i] {};     // Error: by-reference capture when by-reference is the default
[&, this] {};   // OK, equivalent to [&]
[&, this, i]{}; // OK, equivalent to [&, i]
[=]{};          // OK: by-copy capture default
[=, &i]{};      // OK: by-copy capture, except i is captured by reference
[=, *this]{};   // until C++17: Error: invalid syntax
                    // since c++17: OK: captures the enclosing S2 by copy
[=, this] {};   // until C++20: Error: this when = is the default
                    // since C++20: OK, same as [=]
auto fun=[](int i)->int {return i;};
std::function<int(int)> fun2=fun;
int(*fun3)(int)=fun;
cout<<fun2(4);
class S {
  int x = 0;
  void f() {
    int i = 0;
//  auto l1 = [i, x]{ use(i, x); };    // error: x is not a variable
    auto l2 = [i, x=x]{ use(i, x); };  // OK, copy capture
    i = 1; x = 1; l2(); // calls use(0,0)
    auto l3 = [i, &x=x]{ use(i, x); }; // OK, reference capture
    i = 2; x = 2; l3(); // calls use(1,2)
  }
};
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
 
int main()
{
    std::vector<int> c = {1, 2, 3, 4, 5, 6, 7};
    int x = 5;
    c.erase(std::remove_if(c.begin(), c.end(), [x](int n) { return n < x; }), c.end());
 
    std::cout << "c: ";
    std::for_each(c.begin(), c.end(), [](int i){ std::cout << i << ' '; });
    std::cout << '\n';
 
    // the type of a closure cannot be named, but can be inferred with auto
    // since C++14, lambda could own default arguments
    auto func1 = [](int i = 6) { return i + 4; };
    std::cout << "func1: " << func1() << '\n';
 
    // like all callable objects, closures can be captured in std::function
    // (this may incur unnecessary overhead)
    std::function<int(int)> func2 = [](int i) { return i + 4; };
    std::cout << "func2: " << func2(6) << '\n';
}

Function Declaration

Return type deduction
int x = 1;
auto f() { return x; }        // return type is int
const auto& f() { return x; } // return type is const int&
auto f(bool val)
{
    if (val) return 123; // deduces return type int
    else return 3.14f;   // error: deduces return type float
}
auto f() {}              // returns void
auto g() { return f(); } // returns void
auto* x() {}             // error: cannot deduce auto* from void
struct F
{
    virtual auto f() { return 2; } // error virtual function cannot return type deduction
};

declarations examples

int a = 1, *p = NULL, f(), (*pf)(double);
// decl-specifier-seq is int
// declarator f() declares (but doesn't define)
//                a function taking no arguments and returning int
 
struct S
{
    virtual int f(char) const, g(int) &&; // declares two non-static member functions
    virtual int f(char), x; // compile-time error: virtual (in decl-specifier-seq)
                            // is only allowed in declarations of non-static
                            // member functions
};
int f(int a, int *p, int (*(*x)(double))[3]);
int f(int a = 7, int *p = nullptr, int (*(*x)(double))[3] = nullptr);
int f(int, int *, int (*(*)(double))[3]);
int f(int = 7, int * = nullptr, int (*(*)(double))[3] = nullptr);

Default arguments

int fun0(){
    std::vector<int> v{1,2,3,4};
    return v.size();
}
void fun(int i=fun0()){

}

Argument-dependent lookup

int main()
{
    std::cout << "Test\n"; // There is no operator<< in global namespace, but ADL
                           // examines std namespace because the left argument is in
                           // std and finds std::operator<<(std::ostream&, const char*)
    operator<<(std::cout, "Test\n"); // same, using function call notation
 
    // however,
    std::cout << endl; // Error: 'endl' is not declared in this namespace.
                       // This is not a function call to endl(), so ADL does not apply
 
    endl(std::cout); // OK: this is a function call: ADL examines std namespace
                     // because the argument of endl is in std, and finds std::endl
 
    (endl)(std::cout); // Error: 'endl' is not declared in this namespace.
                       // The sub-expression (endl) is not a function call expression
}
using std::swap;
swap(obj1, obj2);
namespace A {
      struct X;
      struct Y;
      void f(int);
      void g(X);
}
 
namespace B {
    void f(int i) {
        f(i);   // calls B::f (endless recursion)
    }
    void g(A::X x) {
        g(x);   // Error: ambiguous between B::g (ordinary lookup)
                //        and A::g (argument-dependent lookup)
    }
    void h(A::Y y) {
        h(y);   // calls B::h (endless recursion): ADL examines the A namespace
                // but finds no A::h, so only B::h from ordinary lookup is used
    }
}

Overload Resolution

struct B { void f(int); };
struct A { operator B&(); };
A a;
a.B::f(1); // Error: user-defined conversions cannot be applied
           // to the implicit object parameter
static_cast<B&>(a).f(1); // OK
int f1(int);
int f2(float);
struct A {
    using fp1 = int(*)(int);
    operator fp1() { return f1; } // conversion function to pointer to function
    using fp2 = int(*)(float);
    operator fp2() { return f2; } // conversion function to pointer to function
} a;
int i = a(1); // calls f1 via pointer returned from conversion function
struct A {
    operator int(); // user-defined conversion
};
A operator+(const A&, const A&); // non-member user-defined operator
void m()
{
    A a, b;
    a + b; // member-candidates: none
           // non-member candidates: operator+(a,b)
           // built-in candidates: int(a) + int(b)
           // overload resolution chooses operator+(a,b)
}
struct Y { operator int*(); };  // Y is convertible to int*
int *a = Y() + 100.0; // error: no operator+ between pointer and double

Viable functions

struct A { A(int); };
struct B { B(A); };
B b{ {0} }; // list-init of B
// candidates: B(const B&), B(B&&), B(A)
// {0} -> B&& not viable: would have to call B(A)
// {0} -> const B&: not viable: would have to bind to rvalue, would have to call B(A)
// {0} -> A viable. Calls A(int): user-defined conversion to A is not banned
template<class T> struct A {
    using value_type = T;
    A(value_type);                  // #1
    A(const A&);                    // #2
    A(T, T, int);                   // #3
    template<class U> A(int, T, U); // #4
};                                 
A x (1, 2, 3);  // uses #3, generated from a non-template constructor
A a (42); // uses #6 to deduce A<int> and #1 to initialize
A b = a;  // uses #5 to deduce A<int> and #2 to initialize
A b2 = a;  // uses #7 to deduce A<A<int>> and #1 to initialize
void Fcn(const int*, short); // overload #1
void Fcn(int*, int); // overload #2
int i;
short s = 0;
void f() 
{
    Fcn(&i, 1L);  // 1st argument: &i -> int* is better than &i -> const int*
                  // 2nd argument: 1L -> short and 1L -> int are equivalent
                  // calls Fcn(int*, int)
 
    Fcn(&i,'c');  // 1st argument: &i -> int* is better than &i -> const int*
                  // 2nd argument: 'c' -> int is better than 'c' -> short
                  // calls Fcn(int*, int)
 
    Fcn(&i, s);   // 1st argument: &i -> int* is better than &i -> const int*
                  // 2nd argument: s -> short is better than s -> int
                  // no winner, compilation error
}

Ranking of implicit conversion sequences

struct Base {};
struct Derived : Base {} d;
int f(Base&);    // overload #1
int f(Derived&); // overload #2
int i = f(d); // d -> Derived& has rank Exact Match
              // d -> Base& has rank Conversion
              // calls f(Derived&)
int i;
int f1();
int g(const int&);  // overload #1
int g(const int&&); // overload #2
int j = g(i);    // lvalue int -> const int& is the only valid conversion
int k = g(f1()); // rvalue int -> const int&& better than rvalue int -> const int&
int f(void(&)());  // overload #1
int f(void(&&)()); // overload #2
void g();
int i1 = f(g);     // calls #1
int f(const int &); // overload #1
int f(int &);       // overload #2 (both references)
int g(const int &); // overload #1
int g(int);         // overload #2
int i;
int j = f(i); // lvalue i -> int& is better than lvalue int -> const int&
              // calls f(int&)
int k = g(i); // lvalue i -> const int& ranks Exact Match
              // lvalue i -> rvalue int ranks Exact Match
              // ambiguous overload: compilation error
int f(const int*);
int f(int*);
int i;
int j = f(&i); // &i -> int* is better than &i -> const int*, calls f(int*)
struct A {
    operator short(); // user-defined conversion function
} a;
int f(int);   // overload #1
int f(float); // overload #2
int i = f(a); // A -> short, followed by short -> int (rank Promotion)
              // A -> short, followed by short -> float (rank Conversion)
              // calls f(int)

Implicit conversion sequence in list-initialization

void f1(int);                                 // #1
void f1(std::initializer_list<long>);         // #2
void g1() { f1({42}); }                       // chooses #2
 
void f2(std::pair<const char*, const char*>); // #3
void f2(std::initializer_list<std::string>);  // #4
void g2() { f2({"foo","bar"}); }              // chooses #4
void f(int    (&&)[] );    // overload #1
void f(double (&&)[] );    // overload #2
void f(int    (&&)[2]);    // overload #3
 
f({1});          // #1: Better than #2 due to conversion, better than #3 due to bounds
f({1.0});        // #2: double -> double is better than double -> int
f({1.0, 2.0});   // #2: double -> double is better than double -> int
f({1, 2});       // #3: -> int[2] is better than -> int[], 
                 //     and int -> int is better than int -> double
struct A { int x, y; };
struct B { int y, x; };
 
void f(A a, int); // #1
void f(B b, ...); // #2
void g(A a); // #3
void g(B b); // #4
 
void h() 
{
    f({.x = 1, .y = 2}, 0); // OK; calls #1
    f({.y = 2, .x = 1}, 0); // error: selects #1, initialization of a fails
                            // due to non-matching member order
    g({.x = 1, .y = 2}); // error: ambiguous between #3 and #4
}
struct A { A(std::initializer_list<int>); };
void f(A);
struct B { B(int, double); };
void g(B);
g({'a','b'});  // calls g(B(int,double)), user-defined conversion
// g({1.0, 1,0}); // error: double->int is narrowing, not allowed in list-init
void f(B);
// f({'a','b'}); // f(A) and f(B) both user-defined conversions
struct A { int m1; double m2;};
void f(A);
f({'a','b'});  // calls f(A(int,double)), user-defined conversion

operator overloading

assignmentincrement
decrement
arithmeticlogicalcomparisonmember
access
other
a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b
++a
–a
a++
a–
+a
-a
a + b
a – b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b
!a
a && b
a || b
a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b
a[b]
*a
&a
a->b
a.b
a->*b
a.*b
a(…)
a, b
? :

static_cast converts one type to another related type
dynamic_cast converts within inheritance hierarchies
const_cast adds or removes cv qualifiers
reinterpret_cast converts type to unrelated type
C-style cast converts one type to another by a mix of static_castconst_cast, and reinterpret_cast
new creates objects with dynamic storage duration
delete destructs objects previously created by the new expression and releases obtained memory area
sizeof queries the size of a type
sizeof… queries the size of a parameter pack (since C++11)
typeid queries the type information of a type
noexcept checks if an expression can throw an exception (since C++11)
alignof queries alignment requirements of a type (since C++11)

(since C++20) && || ++ — , ->* -> ( ) [ ]

std::string str = "Hello, ";
str.operator+=("world");                       // same as str += "world";
operator<<(operator<<(std::cout, str) , '\n'); // same as std::cout << str << '\n';
                                               // (since C++17) except for sequencing

assignment operator

T& operator=(const T& other) // copy assignment
{
    if (this != &other) { // self-assignment check expected
        if (other.size != size) {         // storage cannot be reused
            delete[] mArray;              // destroy storage in this
            size = 0;
            mArray = nullptr;             // preserve invariants in case next line throws
            mArray = new int[other.size]; // create storage in this
            size = other.size;
        } 
        std::copy(other.mArray, other.mArray + other.size, mArray);
    }
    return *this;
}
T& operator=(T&& other) noexcept // move assignment
{
    if(this != &other) { // no-op on self-move-assignment (delete[]/size=0 also ok)
        delete[] mArray;                               // delete this storage
        mArray = std::exchange(other.mArray, nullptr); // leave moved-from in valid state
        size = std::exchange(other.size, 0);
    }
    return *this;
}
T& T::operator=(T arg) noexcept // copy/move constructor is called to construct arg
{
    std::swap(size, arg.size); // resources are exchanged between *this and arg
    std::swap(mArray, arg.mArray);
    return *this;
}

example

class Fraction
{
    int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
    int n, d;
public:
    Fraction(int n, int d = 1) : n(n/gcd(n, d)), d(d/gcd(n, d)) { }
    int num() const { return n; }
    int den() const { return d; }
    Fraction& operator*=(const Fraction& rhs)
    {
        int new_n = n * rhs.n/gcd(n * rhs.n, d * rhs.d);
        d = d * rhs.d/gcd(n * rhs.n, d * rhs.d);
        n = new_n;
        return *this;
    }
};
std::ostream& operator<<(std::ostream& out, const Fraction& f)
{
   return out << f.num() << '/' << f.den() ;
}
bool operator==(const Fraction& lhs, const Fraction& rhs)
{
    return lhs.num() == rhs.num() && lhs.den() == rhs.den();
}
bool operator!=(const Fraction& lhs, const Fraction& rhs)
{
    return !(lhs == rhs);
}
Fraction operator*(Fraction lhs, const Fraction& rhs)
{
    return lhs *= rhs;
}
 
int main()
{
   Fraction f1(3, 8), f2(1, 2), f3(10, 2);
   std::cout << f1 << " * " << f2 << " = " << f1 * f2 << '\n'
             << f2 << " * " << f3 << " = " << f2 * f3 << '\n'
             <<  2 << " * " << f1 << " = " <<  2 * f1 << '\n';
}

Address of an overloaded function

int f(int) { return 1; }
int f(double) { return 2; }
 
void g( int(&f1)(int), int(*f2)(double) ) {}
 
template< int(*F)(int) >
struct Templ {};
 
struct Foo {
    int mf(int) { return 3; }
    int mf(double) { return 4; }
};
 
struct Emp {
    void operator<<(int (*)(double)) {}
};
 
int main()
{
    // 1. initialization
    int (*pf)(double) = f; // selects int f(double)
    int (&rf)(int) = f; // selects int f(int)
    int (Foo::*mpf)(int) = &Foo::mf; // selects int mf(int)
 
    // 2. assignment
    pf = nullptr;
    pf = &f; // selects int f(double)
 
    // 3. function argument
    g(f, f); // selects int f(int) for the 1st argument
             // and int f(double) for the second
 
    // 4. user-defined operator
    Emp{} << f; //selects int f(double)
 
    // 5. return value
    auto foo = []() -> int (*)(int) {
        return f; // selects int f(int)
    };
 
    // 6. cast
    auto p = static_cast<int(*)(int)>(f); // selects int f(int)
 
    // 7. template argument
    Templ<f> t;  // selects int f(int)
}

Declarations in c++

Enum

enum name { enumerator = constexpr , enumerator = constexpr , … }
enum name : type { enumerator = constexpr , enumerator = constexpr , … }
enum name : type ;
enum A{
    One=0,
    Two=1,
    Three=3
};
class AA{
public:
    enum A{
        One=0,
        Two=1,
        Three=3
    };
};
int main(int _argc,char* _argv[]){
    int l=::A::One;
    l=::One;
    ::A a=(::A)1;
    AA::A aa=AA::One;
    aa=AA::A::One;
}
enum num : char { one = '0' };
std::cout << num::one; // '0', not 48
enum Foo { a, b, c = 10, d, e = 1, f, g = f + c };
//a = 0, b = 1, c = 10, d = 11, e = 1, f = 2, g = 12

Array

int a[2];            // array of 2 int
int* p1 = a;         // a decays to a pointer to the first element of a
 
int b[2][3];         // array of 2 arrays of 3 int
// int** p2 = b;     // error: b does not decay to int**
int (*p2)[3] = b;    // b decays to a pointer to the first 3-element row of b
 
int c[2][3][4];      // array of 2 arrays of 3 arrays of 4 int
// int*** p3 = c;    // error: c does not decay to int***
int (*p3)[3][4] = c; // c decays to a pointer to the first 3 × 4-element plane of c
int l[]{1,2,3,4,5,6,7};//or = {1,2,3,4,5,6,7};
int m=*(l+4);
//l++ ++l errors
int* k=new int[5]{1,2,3,4,5};
void g(int (&a)[3])
{
    std::cout << a[0] << '\n';
}
 
void f(int* p)
{
    std::cout << *p << '\n';
}
 
int main()
{
    int a[3] = {1, 2, 3};
    int* p = a;
 
    std::cout << sizeof a << '\n'  // prints size of array
              << sizeof p << '\n'; // prints size of a pointer
 
    // where arrays are acceptable, but pointers aren't, only arrays may be used
    g(a); // okay: function takes an array by reference
//  g(p); // error
 
    for(int n: a)              // okay: arrays can be used in range-for loops
        std::cout << n << ' '; // prints elements of the array
//  for(int n: p)              // error
//      std::cout << n << ' ';
 
    // where pointers are acceptable, but arrays aren't, both may be used:
    f(a); // okay: function takes a pointer
    f(p); // okay: function takes a pointer
 
    std::cout << *a << '\n' // prints the first element
              << *p << '\n' // same
              << *(a + 1) << ' ' << a[1] << '\n'  // prints the second element
              << *(p + 1) << ' ' << p[1] << '\n'; // same
}

Namespace

namespace Q {
  namespace V { // original-namespace-definition for V
    void f(); // declaration of Q::V::f
  }
  void V::f() {} // OK
  void V::g() {} // Error: g() is not yet a member of V
  namespace V { // extension-namespace-definition for V
    void g(); // declaration of Q::V::g
  }
}
namespace R { // not a enclosing namespace for Q
   void Q::V::g() {} // Error: cannot define Q::V::g inside R
}
void Q::V::g() {} // OK: global namespace encloses Q
namespace D {
   int d1;
   void f(char);
}
using namespace D; // introduces D::d1, D::f, D::d2, D::f,
                   //  E::e, and E::f into global namespace!
 
int d1; // OK: no conflict with D::d1 when declaring
namespace E {
    int e;
    void f(int);
}
namespace D { // namespace extension
    int d2;
    using namespace E; // transitive using-directive
    void f(int);
}
void f() {
    d1++; // error: ambiguous ::d1 or D::d1?
    ::d1++; // OK
    D::d1++; // OK
    d2++; // OK, d2 is D::d2
    e++; // OK: e is E::e due to transitive using
    f(1); // error: ambiguous: D::f(int) or E::f(int)?
    f('a'); // OK: the only f(char) is D::f(char)
}
namespace vec {
 
    template< typename T >
    class vector {
        // ...
    };
 
} // of vec
 
int main()
{
    std::vector<int> v1; // Standard vector.
    vec::vector<int> v2; // User defined vector.
 
    v1 = v2; // Error: v1 and v2 are different object's type.
 
    {
        using namespace std;
        vector<int> v3; // Same as std::vector
        v1 = v3; // OK
    }
 
    {
        using vec::vector;
        vector<int> v4; // Same as vec::vector
        v2 = v4; // OK
    }
 
    return 0;
}
namespace foo {
    namespace bar {
         namespace baz {
             int qux = 42;
         }
    }
}
 
namespace fbz = foo::bar::baz;
 
int main()
{
    std::cout << fbz::qux << '\n';
}

Reference declaration

int& a[3]; // error
int&* p;   // error
int& &r;   // error

typedef int&  lref;
typedef int&& rref;
int n;
lref&  r1 = n; // type of r1 is int&
lref&& r2 = n; // type of r2 is int&
rref&  r3 = n; // type of r3 is int&
rref&& r4 = 1; // type of r4 is int&&
void f(int& x) {
    std::cout << "lvalue reference overload f(" << x << ")\n";
}
 
void f(const int& x) {
    std::cout << "lvalue reference to const overload f(" << x << ")\n";
}
 
void f(int&& x) {
    std::cout << "rvalue reference overload f(" << x << ")\n";
}
 
int main() {
    int i = 1;
    const int ci = 2;
    f(i);  // calls f(int&)
    f(ci); // calls f(const int&)
    f(3);  // calls f(int&&)
           // would call f(const int&) if f(int&&) overload wasn't provided
    f(std::move(i)); // calls f(int&&)
 
    // rvalue reference variables are lvalues when used in expressions
    int&& x = 1;
    f(x);            // calls f(int& x)
    f(std::move(x)); // calls f(int&& x)
}

forwarding

template<class T>
int f(T&& x) {                    // x is a forwarding reference
    return g(std::forward<T>(x)); // and so can be forwarded
}
 
int main() {
    int i;
    f(i); // argument is lvalue, calls f<int&>(int&), std::forward<int&>(x) is lvalue
    f(0); // argument is rvalue, calls f<int>(int&&), std::forward<int>(x) is rvalue
}
 
template<class T>
int g(const T&& x); // x is not a forwarding reference: const T is not cv-unqualified
 
template<class T> struct A {
    template<class U>
    A(T&& x, U&& y, int* p); // x is not a forwarding reference: T is not a
                             // type template parameter of the constructor,
                             // but y is a forwarding reference
};

Pointer

pointer to object

struct C {
   int x, y;
} c;
 
int* px = &c.x;   // value of px is "pointer to c.x"
int* pxe= px + 1; // value of pxe is "pointer past the end of c.x"
int* py = &c.y;   // value of py is "pointer to c.y"
 
assert(pxe == py); // == tests if two pointers represent the same address
                   // may or may not fire
 
*pxe = 1; // undefined behavior even if the assertion does not fire
int n;
int* np = &n; // pointer to int
int* const* npp = &np; // non-const pointer to const pointer to non-const int
 
int a[2];
int (*ap)[2] = &a; // pointer to array of int
 
struct S { int n; };
S s = {1};
int* sp = &s.n; // pointer to the int that is a member of s
int n;
int* p = &n;     // pointer to n
int& r = *p;     // reference is bound to the lvalue expression that identifies n
r = 7;           // stores the int 7 in n
std::cout << *p; // lvalue-to-rvalue implicit conversion reads the value from n
int a[2];
int* p1 = a; // pointer to the first element a[0] (an int) of the array a
 
int b[6][3][8];
int (*p2)[3][8] = b; // pointer to the first element b[0] of the array b,
                     // which is an array of 3 arrays of 8 ints

struct Base {};
struct Derived : Base {};
 
Derived d;
Base* p = &d;

const pointer

Syntaxmeaning
const T*pointer to constant object
T const*pointer to constant object
T* constconstant pointer to object
const T* constconstant pointer to constant object
T const* constconstant pointer to constant object
const int* const i=new int ;
const int* const* ii=&i;//non-const pointer to const pointer to const object
const int n1=12;
const int* n2=&n1;//int* is error 

pointer to void

int n = 1;
int* p1 = &n;
void* pv = p1;
int* p2 = static_cast<int*>(pv);
std::cout << *p2 << '\n'; // prints 1

pointer to functions

int (* f)()f is a pointer to a function with prototype int func().
int (* f())()f is a function taking no inputs and returning a pointer to a function with prototype int func().
int * f()f is a function returning a pointer-to-int.
int (* a[])()a is an array of pointers to functions each with prototype int func().
int (* f())[]f is a function returning a pointer to an array.
int (f[])()Not allowed. Can’t have an array of functions.
int * const *(*g)(float)g is pointer to a function with prototype int * const * func(float) where its return value int * const * is a pointer to a read-only pointer-to-int.
int f();
int (*p)() = f;  // pointer p is pointing to f
int (&r)() = *p; // the lvalue that identifies f is bound to a reference
r();             // function f invoked through lvalue reference
(*p)();          // function f invoked through the function lvalue
p();  

Pointers to data members

struct C { int m; };
 
int main()
{
    int C::* p = &C::m;          // pointer to data member m of class C
    C c = {7};
    std::cout << c.*p << '\n';   // prints 7
    C* cp = &c;
    cp->m = 10;
    std::cout << cp->*p << '\n'; // prints 10
}
struct Base { int m; };
struct Derived : Base {};
 
int main()
{
    int Base::* bp = &Base::m;
    int Derived::* dp = bp;
    Derived d;
    d.m = 1;
    std::cout << d.*dp << ' ' << d.*bp << '\n'; // prints 1 1
}
struct A
{
    int m;
    // const pointer to non-const member
    int A::* const p;
};
 
int main()
{
    // non-const pointer to data member which is a const pointer to non-const member
    int A::* const A::* p1 = &A::p;
 
    const A a = {1, &A::m};
    std::cout << a.*(a.*p1) << '\n'; // prints 1
 
    // regular non-const pointer to a const pointer-to-member
    int A::* const* p2 = &a.p;
    std::cout << a.**p2 << '\n'; // prints 1
}

Pointers to function members

struct Base
{
    void f(int n) { std::cout << n << '\n'; }
};
struct Derived : Base {};
 
int main()
{
    void (Base::* bp)(int) = &Base::f;
    void (Derived::* dp)(int) = bp;
    Derived d;
    (d.*dp)(1);
    (d.*bp)(2);
}
struct Base {};
struct Derived : Base
{
    void f(int n) { std::cout << n << '\n'; }
};
 
int main()
{
    void (Derived::* dp)(int) = &Derived::f;
    void (Base::* bp)(int) = static_cast<void (Base::*)(int)>(dp);
 
    Derived d;
    (d.*bp)(1); // okay: prints 1
 
    Base b;
    (b.*bp)(2); // undefined behavior
}

null pointer

To initialize a pointer to null or to assign the null value to an existing pointer, the null pointer literal nullptr, the null pointer constant NULL, or the implicit conversion from the integer value ​0​ may be used.

const and volatile and Mutable

int main()
{
    int n1 = 0;           // non-const object
    const int n2 = 0;     // const object
    int const n3 = 0;     // const object (same as n2)
    volatile int n4 = 0;  // volatile object
    const struct
    {
        int n1;
        mutable int n2;
    } x = {0, 0};      // const object with mutable member
 
    n1 = 1; // ok, modifiable object
//  n2 = 2; // error: non-modifiable object
    n4 = 3; // ok, treated as a side-effect
//  x.n1 = 4; // error: member of a const object is const
    x.n2 = 4; // ok, mutable member of a const object isn't const
 
    const int& r1 = n1; // reference to const bound to non-const object
//  r1 = 2; // error: attempt to modify through reference to const
    const_cast<int&>(r1) = 2; // ok, modifies non-const object n1
 
    const int& r2 = n2; // reference to const bound to const object
//  r2 = 2; // error: attempt to modify through reference to const
//  const_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2
}
class Test { 
public: 
  int x; 
  mutable int y; 
  Test() { x = 4; y = 10; } 
}; 
int main() 
{ 
    const Test t1; 
    t1.y = 20; 
    cout << t1.y; 
    return 0; 
}
class Customer 
{ 
    char name[25]; 
    mutable char placedorder[50]; 
    int tableno; 
    mutable int bill; 
public: 
    Customer(char* s, char* m, int a, int p) 
    { 
        strcpy(name, s); 
        strcpy(placedorder, m); 
        tableno = a; 
        bill = p; 
    } 
    void changePlacedOrder(char* p) const
    { 
        strcpy(placedorder, p); 
    } 
    void changeBill(int s) const
    { 
        bill = s; 
    } 
    void display() const
    { 
        cout << "Customer name is: " << name << endl; 
        cout << "Food ordered by customer is: " << placedorder << endl; 
        cout << "table no is: " << tableno << endl; 
        cout << "Total payable amount: " << bill << endl; 
    } 
}; 

constexpr specifier

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

#include <iostream>
#include <stdexcept>
 
// C++11 constexpr functions use recursion rather than iteration
// (C++14 constexpr functions may use local variables and loops)
constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}
 
// literal class
class conststr {
    const char* p;
    std::size_t sz;
public:
    template<std::size_t N>
    constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}
 
    // constexpr functions signal errors by throwing exceptions
    // in C++11, they must do so from the conditional operator ?:
    constexpr char operator[](std::size_t n) const
    {
        return n < sz ? p[n] : throw std::out_of_range("");
    }
    constexpr std::size_t size() const { return sz; }
};
 
// C++11 constexpr functions had to put everything in a single return statement
// (C++14 doesn't have that requirement)
constexpr std::size_t countlower(conststr s, std::size_t n = 0,
                                             std::size_t c = 0)
{
    return n == s.size() ? c :
           'a' <= s[n] && s[n] <= 'z' ? countlower(s, n + 1, c + 1) :
                                       countlower(s, n + 1, c);
}
 
// output function that requires a compile-time constant, for testing
template<int n>
struct constN
{
    constN() { std::cout << n << '\n'; }
};
 
int main()
{
    std::cout << "4! = " ;
    constN<factorial(4)> out1; // computed at compile time
 
    volatile int k = 8; // disallow optimization using volatile
    std::cout << k << "! = " << factorial(k) << '\n'; // computed at run time
 
    std::cout << "the number of lowercase letters in \"Hello, world!\" is ";
    constN<countlower("Hello, world!")> out2; // implicitly converted to conststr
}

decltype 

struct A { double x; };
const A* a;
 
decltype(a->x) y;       // type of y is double (declared type)
decltype((a->x)) z = y; // type of z is const double& (lvalue expression)
 
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // return type depends on template parameters
                                      // return type can be deduced since C++14
{
    return t+u;
}
 
int main() 
{
    int i = 33;
    decltype(i) j = i * 2;
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
 
    auto f = [](int a, int b) -> int
    {
        return a * b;
    };
 
    decltype(f) g = f; // the type of a lambda function is unique and unnamed
    i = f(2, 2);
    j = g(3, 3);
 
    std::cout << "i = " << i << ", "
              << "j = " << j << '\n';
}

auto

#include <iostream>
#include <utility>

template<class T, class U>
auto add(T t, U u) { return t + u; } // the return type is the type of operator+(T, U)

// perfect forwarding of a function call must use decltype(auto)
// in case the function it calls returns by reference
template<class F, class... Args>
decltype(auto) PerfectForward(F fun, Args&&... args)
{
    return fun(std::forward<Args>(args)...);
}

template<auto n> // C++17 auto parameter declaration
auto f() -> std::pair<decltype(n), decltype(n)> // auto can't deduce from brace-init-list
{
    return {n, n};
}

int main()
{
    auto a = 1 + 2;            // type of a is int
    auto b = add(1, 1.2);      // type of b is double
    static_assert(std::is_same_v<decltype(a), int>);
    static_assert(std::is_same_v<decltype(b), double>);

    auto c0 = a;             // type of c0 is int, holding a copy of a
    decltype(auto) c1 = a;   // type of c1 is int, holding a copy of a
    decltype(auto) c2 = (a); // type of c2 is int&, an alias of a
    std::cout << "a, before modification through c2 = " << a << '\n';
    ++c2;
    std::cout << "a, after modification through c2 = " << a << '\n';

    auto [v, w] = f<0>(); //structured binding declaration
    std::cout<<v<<w;

    auto d = {1, 2}; // OK: type of d is std::initializer_list<int>
    auto n = {5};    // OK: type of n is std::initializer_list<int>
//  auto e{1, 2};    // Error as of C++17, std::initializer_list<int> before
    auto m{5};       // OK: type of m is int as of C++17, initializer_list<int> before
//  decltype(auto) z = { 1, 2 } // Error: {1, 2} is not an expression

    // auto is commonly used for unnamed types such as the types of lambda expressions
    auto lambda = [](int x) { return x + 3; };

//  auto int x; // valid C++98, error as of C++11
//  auto x;     // valid C, error in C++
}

decltype(auto)

 in generic code you want to be able to perfectly forward a return type without knowing whether you are dealing with a reference or a value. decltype(auto) gives you that ability:

int i;
int&& f();
auto x3a = i;                  // decltype(x3a) is int
decltype(auto) x3d = i;        // decltype(x3d) is int
auto x4a = (i);                // decltype(x4a) is int
decltype(auto) x4d = (i);      // decltype(x4d) is int&
auto x5a = f();                // decltype(x5a) is int
decltype(auto) x5d = f();      // decltype(x5d) is int&&
auto x6a = { 1, 2 };           // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i;                // decltype(x7a) is int*
decltype(auto)*x7d = &i;       // error, declared type is not plain decltype(auto)
template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}

Delaying return type deduction in recursive templates

template<int i> 
struct Int {};

constexpr auto iter(Int<0>) -> Int<0>;

template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) 
{ return iter(Int<i-1>{}); }

int main() { decltype(iter(Int<10>{})) a; }

Elaborated type

enum A { A_START = 0 };

void A(enum A a) {}

int main() {
   enum A a;
   A( a );
}
template <typename T>
struct Node {
    struct Node* Next; // OK: lookup of Node finds the injected-class-name
    struct Data* Data; // OK: declares type Data at global scope
                       // and also declares the data member Data
    friend class ::List; // error: cannot introduce a qualified name
    enum Kind* kind; // error: cannot introduce an enum
};
 
Data* p; // OK: struct Data has been declared