Created
June 13, 2017 16:53
-
-
Save samehkamaleldin/deea3ccb85b5e39609f2ded0d04c6a85 to your computer and use it in GitHub Desktop.
Demo for some of C++11 capabilities
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <map> | |
#include <string> | |
#include <memory> | |
#include <functional> | |
using namespace std; | |
// usage of auto as function return type that depends on template params | |
template <typename T1, typename T2> | |
auto sum_types(T1 t1, T2 t2) -> decltype(t1 + t2) | |
{ | |
return t1+t2; | |
} | |
// functions used in tut sections | |
void fn (char* c ){} | |
void fn (int n ){} | |
void disp (char c ){cout << c;} | |
int sum (int a,int b){return a+b;} | |
// display section name in stdout | |
void section(string name){ | |
cout << endl << string(70, '#') << endl; | |
cout << "# " << name << endl << endl; | |
} | |
// struct used in tut sections | |
struct Foo | |
{ | |
Foo() { std::cout << "> Foo::Foo \n"; } | |
~Foo() { std::cout << "> Foo::~Foo\n"; } | |
void bar() { std::cout << "> Foo::bar \n"; } | |
}; | |
constexpr double metre(1.0); | |
constexpr double gram (1.0); | |
// a user defined litral | |
constexpr double operator "" _kg(long double q){return q*1000;} | |
constexpr double operator "" _g (long double q){return q; } | |
int main(int argc, char** argv) | |
{ | |
// --------------------------------------------------------------------------- | |
// Feature : List initialization : | |
// Summary : initialize an object from braced-init-list : | |
// Reference : http://en.cppreference.com/w/cpp/language/list_initialization : | |
// --------------------------------------------------------------------------- | |
section("List initialization"); | |
//simple initialization of a typed vector using list initialization | |
vector<int> numbers { 1, 2, 3, 4, 5}; | |
cout << "numbers[02]: " << numbers.at(0) << endl; | |
vector<string> names { "Ahmed", "Khalid", "Anas", "Heba", "Omar"}; | |
cout << "names[2]: " << names.at(2) << endl; | |
// string can be initialized as list of chars | |
string word { 'w', 'o', 'r', 'd'}; | |
cout << "word string: " << word << endl; | |
// using nested list initialization | |
map<int,string> ids { {1,"KQ"}, {2,{'R','A'}}, {3,{'M',0x65}} }; | |
// empty list initialization is zero | |
int zero{}; | |
// --------------------------------------------------------------------------- | |
// Feature : auto specifier : | |
// Summary : specify that variable type will be deduced from initializer : | |
// Reference : http://en.cppreference.com/w/cpp/language/auto : | |
// --------------------------------------------------------------------------- | |
section("auto specifier"); | |
// initialize different types using auto | |
auto name = "Ali"; | |
auto age = 23; | |
auto alive = true; | |
cout <<"- " << name << " is " << age << " years old." << endl; | |
// usage of auto as a function return type | |
auto res = sum_types(3,12.1); | |
cout << "- Result is " << res << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : Range-based for loops : | |
// Summary : Executes a for loop over a range : | |
// Reference : http://en.cppreference.com/w/cpp/language/range-for : | |
// --------------------------------------------------------------------------- | |
section("range-based for loop"); | |
// sum pre-defined numbers vector to stdout | |
int summation{}; | |
for(auto num : numbers) | |
summation += num; | |
cout << "- summation of numbers = " << summation << endl; | |
// loop over list initializer | |
cout << "- animals: [ "; | |
for(auto animal : { "monkey", "lion", "elephant"}) | |
cout << animal << " "; | |
cout << "- ]" << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : std :: nullptr - null pointer : | |
// Summary : There exist implicit conversions from nullptr to null pointer : | |
// value of any pointer type and any pointer to member type : | |
// Reference : http://en.cppreference.com/w/cpp/language/nullptr : | |
// --------------------------------------------------------------------------- | |
section("std::nullptr"); | |
// [Ref]: http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr \ | |
// #comment1111836_1282345] | |
// | |
// Note that NULL is not even guaranteed to be 0. It can be 0L, | |
// in which case a call to void f(int); void f(char *); will be ambiguous. | |
// nullptr will always favor the pointer version, and never call the int one. | |
// Also note that nullptr is convertible to bool | |
// nullptr will work | |
fn(nullptr); | |
// This is ambigous and omits error | |
// fn(NULL); | |
// both nullptr and NULL can be converted to bool | |
bool bvaln = nullptr; | |
bool bvalN = NULL; | |
// error as nullptr can't be casted to int | |
//int ivaln = nullptr; | |
// will work but will show a warning | |
// int ivalN = NULL; | |
// --------------------------------------------------------------------------- | |
// Feature : std :: shared_ptr - defined in <memory> header : | |
// Summary : Smart pointer that automatically destroy non-used objects : | |
// Reference : http://en.cppreference.com/w/cpp/memory/shared_ptr : | |
// --------------------------------------------------------------------------- | |
section("std::shared_ptr"); | |
// std::shared_ptr is a smart pointer that retains shared ownership | |
// of an object through a pointer. Several shared_ptr objects may own | |
// the same object. The object is destroyed and its memory deallocated | |
// when either of the following happens: | |
// 1- the last remaining shared_ptr owning the object is destroyed. | |
// 2- the last remaining shared_ptr owning the object is assigned | |
// another pointer via operator= or reset(). | |
// just use it instead of normal pointer to get rid of delete part | |
char* c_normal(nullptr); | |
shared_ptr<char> c_shared(nullptr); | |
// creating two versions of pointer to struct | |
Foo* p_normal(new Foo); | |
shared_ptr<Foo> p_shared(new Foo); | |
// set normal pointer to null [ object not deleted] | |
cout << "- normal ptr set to null" << endl; | |
p_normal = nullptr; | |
cout << "- normal ptr didn't delete the object" << endl; | |
// set shared pointer to null, destructor called, see output. | |
cout << "- shared ptr set to null" << endl; | |
p_shared = nullptr; | |
cout << "- normal ptr deleted the object [ destructor called ]" << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : std :: unique_ptr - defined in <memory> header : | |
// Summary : Smart pointer that holds a non sharable reference to value : | |
// Reference : http://en.cppreference.com/w/cpp/memory/unique_ptr : | |
// --------------------------------------------------------------------------- | |
section("std::unique_ptr"); | |
// std::unique_ptr is a smart pointer that retains sole ownership of | |
// an object through a pointer and destroys that object when the unique_ptr | |
// goes out of scope. | |
// No two unique_ptr instances can manage the same object. | |
// The object is destroyed and its memory deallocated when either of | |
// the following happens: | |
// 1- unique_ptr managing the object is destroyed | |
// 2- unique_ptr managing the object is assigned another pointer | |
// via operator= or reset(). | |
// initialze two unique pointer | |
unique_ptr<Foo> u_ptr1(new Foo); // uptr1 owns Foo | |
unique_ptr<Foo> u_ptr2(nullptr); | |
// check if unqie pointer 1 owns reference | |
if(u_ptr1) | |
cout << "- u_ptr1 owns reference" << endl; | |
else | |
cout << "- u_ptr1 owns nothing" << endl; | |
// move ownership to uptr2 | |
u_ptr2 = move(u_ptr1); | |
cout << "- ownership transfered to u_ptr2" <<endl; | |
// check if unqie pointer 1 owns reference | |
if(u_ptr1) | |
cout << "- u_ptr1 owns reference" << endl; | |
else | |
cout << "- u_ptr1 owns nothing" << endl; | |
if(u_ptr2) | |
cout << "- u_ptr2 owns reference" << endl; | |
else | |
cout << "- u_ptr2 owns nothing" << endl; | |
// reset u_ptr2; | |
u_ptr2.reset(); | |
cout << "- reset u_ptr2 object deleted [destructor called]" << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : std :: function defined in <functional> header : | |
// Summary : lass template std::function is a function wrapper : | |
// Reference : http://en.cppreference.com/w/cpp/language/lambda : | |
// --------------------------------------------------------------------------- | |
section("std::function"); | |
// initialize two function objects | |
function<void(char )> func = disp; | |
function<int (int,int)> func_sum = sum; | |
// call the initialized function objects | |
cout << "- call function [disp]: "; | |
func('2'); | |
cout << endl; | |
cout << "- call function [sum]: "; | |
cout << "- 3 + 4 = " << func_sum(3,4) << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : Lambda Functions : | |
// Summary : Creates anonymous function object that can read objects : | |
// Reference : http://en.cppreference.com/w/cpp/language/lambda : | |
// --------------------------------------------------------------------------- | |
section("lambda functions"); | |
// simplist form of lambda function that do nothing - void(void){} | |
[](){}; | |
// labmda function can be assigned to std :: function | |
auto lm_empty_fn = [](){}; | |
// no args lambda fn that show a message | |
auto lm_msg_fn = [](){cout << "- hello from lambda fn" << endl; }; | |
lm_msg_fn(); | |
// one arg lambda fn that greet a name | |
auto lm_greet_fn = [](string name_str){cout << "- hi " << name_str << endl; }; | |
lm_greet_fn("Ali"); | |
// lambda function can be call instanteously | |
[](){cout << "- this is instanteously called lambda fn" << endl; }(); | |
// lambda fn capture variables can be values or references | |
int a = 8; | |
[a](int x){return x + a; }; | |
// passing function as capture and call lambda fn instanteously | |
int lm_sum = [a,func_sum](int b){ return func_sum(a,b); }(9); | |
cout << "- lambda fn with function as capture: sum is " << lm_sum << endl; | |
// explicit definition of lambda fn is offered to solve ambigious returns | |
[]()-> double {return 2.3;}; | |
// --------------------------------------------------------------------------- | |
// Feature : User Defined Litarals : | |
// Summary : produce objects of user-defined type by a user-defined suffix : | |
// Reference : http://en.cppreference.com/w/cpp/language/user_literal : | |
// --------------------------------------------------------------------------- | |
section("user defined literals"); | |
// usage of user defined literals [ definition located before main ] | |
double weight_in_kg = 13.5_kg; | |
double weight_in_g = 13500.0_g; | |
if (weight_in_g == weight_in_kg) | |
cout << "- 13.5 kg == 13500 g" << endl; | |
// --------------------------------------------------------------------------- | |
// Feature : User Defined Litarals : | |
// Summary : produce objects of user-defined type by a user-defined suffix : | |
// Reference : http://en.cppreference.com/w/cpp/language/user_literal : | |
// --------------------------------------------------------------------------- | |
section("static_assert"); | |
// static assert is assert in compile time, that if condition is true nothing | |
// happens otherwise it omits the specified error messages | |
const int big_num1 = 300; | |
const int big_num2 = 67; | |
// this won't omit compiler error as it's true | |
static_assert( big_num1 > 100 , "this number is not odd"); | |
// the next will omit a comiler error | |
//static_assert( big_num2 > 100 , "this number is not odd"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment