Initializer_list

C++{11} bring into old c++ world a lot of exciting new features! One of this features is [std::initializer_list](http://en.cppreference.com/w/cpp/utility/initializer_list). This new data structure is just a lightweight proxy object that provides access to the array of objects of type `const T`, in few words it's just array but not std::array. Using this data structure with keyword `auto` so easy and cool like drive a supercar.

//arr is std::initializer_list<int>
auto arr = {1,2,3,4,5};
for(auto& elem: arr){
	std::cout<<elem<<' '; //will print 1 2 3 4 5
}
//OR
for(auto& val: {1,3,5,7,11}){
	std::cout<<val<<' '; //will print 1 3 5 7 11
}

Wow, it’s really easy! By default, if you write auto with braced-init-list({}) as we can see in the code above, you create a std::initializer_list instance. But c++{11} went further and add this feature to [list-initialization](http://en.cppreference.com/w/cpp/language/list_initialization) like function call, and assignment expression when argument is `std::initializer_list`. But my favorite feature is using std::initializer_list with constructors, this will make it possible to do something like this:

std::vector<int> vec {1,2,3,4,5,6,7}; //constructor
std::vector<int> vec_1 = {1,2,3,4,5,6,7}; //assigment
auto vec_2 = vector<int>{1,2,3,4,5,6}; //constructor
auto vec_3 = vector<int>({1,2,3,4,5,6}); //constructor

All of this 4 vectors will contain the same values, and it’s really easy to initialize objects in this way. By default, if you declare std::initializer_list<T> in your function or constructor as an input argument, compiler prefer this function instead of an overloaded function with the same types and numbers of arguments.

vector<int> vec (10,20); //10 elements, each is 20 
vector<int> vec {10,20}; //2 elements, 10 and 20

As we can see above, when we use braced-init-list compiler prefer call std::vector(std::initializer_list<T>) constructor instead of std::vector(int _a, int _n). Let’s try create our own structure!

template <typename T>
class Container{
private:
    std::vector<T> vec;
public:
    /**
     * Create Container from initializer_list
     * @param list initializer_list
     */
    Container(const std::initializer_list<T>& list){
        this->append(list);
    }
    /**
     * Create Container with default constructed n elements
     * @param size The number of elements to initially create.
     * @param default_value Default value every element
     */
    Container(size_t size, T default_value){
        vec = std::vector<T>(size, default_value);
    }
    /**
     * Append list to end of container
     * @param list appending list 
     * @return pointer to current container
     */
    Container& append(const std::initializer_list<T>& list){
        this->vec.insert(this->vec.end(), list.begin(), list.end());
        return *this;
    }
    /**
     * Get element by index
     * @param index index of element
     * @return reference to element
     */
    T&operator[](const int& index){
        //TODO add bounding checks
        return this->vec[abs(index) % this->vec.size()]; //cycle
    }
};

...

Container<int> container (10,555);
container.append({5,6,7,8});
for(auto i = 0;i < container.size();i++){
    std::cout<<container[i]<<' ';
}
std::cout<<std::endl;
//will print: 555 555 555 555 555 555 555 555 555 555 5 6 7 8 

Container<int> container_1 {10,555};
container_1.append({5,6,7,8});
for(auto i = 0;i < container_1.size();i++){
    std::cout<<container_1[i]<<' ';
}
//will print 10 555 5 6 7 8

Move constructor

If you define class or structure in C++{98} compiller generate 4 member function for you :

  • Default constructor
  • Desctructor
  • Copy constructor (deleted if class contains move operations)
  • Copy assigment operator (deleted if class contains move operations)

In new c++{11} you will have new one special member functions :

These members will be generated if the class contains no user-declared copy operation, destructor or move operations. Each of this function performs memberwise moving of non-static data members.

Let’s take a look at default move constructor:

class Person {
public:
    std::string name;
    //First copy constructor
    Person(const std::string& name):name(name){
    }
    Person(Person&& person) = delete; //delete move constructor
};
class Glass{
public:
    std::string name;
    //First copy constructor
    Glass(std::string&& name):name(std::move(name)){

    }
    //Second move constructor
    Glass(const std::string& name):name(name){

    }
};

...

Person person {"Alfred"}; // call first constructor
Glass red_glass {"brow-blue"}; //call second constuctor

auto newone_red_glass = std::move(red_glass); //call second contructor
//auto new_person = std::move(person); // do not compile cause we delete move constructor

std::cout<<"Red glass name : " << red_glass.name<< std::endl;  
//will print `Red glass name :`
    
std::cout<<"New one Red glass name : " << newone_red_glass.name<< std::endl; 
//will print `New one Red glass name : brow-blue`

As we can see after move operation old value will be moved to new one, in some cases, it’s better than create a copy (like reallocation memory in std::vector c++{11}) cause it’s faster than create a copy.

Variadic template

Variadic template - are a template that takes a variable number of templates. It’s made possible pass different number arguments with different types to function (kind of varargs in java). This feature can be used if you want to implement custom printf function, which retrieves a different number of arguments with different types. Also, all logic will be resolved on compile-time!

//1 argument
template <typename T>
T sum(T value){   
    return value;
}
// Different number of arguments
template <typename T, typename ...Args>
T sum(T value, Args... rest){
    return value + sum(rest...);
};

...

std::cout<<sum(1.1f,2,3,6.0f,0.75); 
//will print: 12.1

This sum function, calculate sum of input arguments, by recursion. First function sum will be called if number of arguments = 1, but if number of arguments will be more than 2, the second function will be called. As you can see we pass the first argument as type float, but second is int. And the output will be cast to type float, cause it’s frirt argument. Let’s try test it :

#include <limits>  //for std::cout.precision
#include <typeinfo> //typeid(t).name

...
std::cout.precision(std::numeric_limits< double >::max_digits10);

auto sum_int = sum(2, 1.1f,2,3,6.0f,0.75, static_cast<double >(5.0 + 1e-12));
std::cout<<"Sum; var sum_int: "<<sum_int<<std::endl;
std::cout<<"Type of sum_int: "<< typeid(sum_int).name()<<std::endl;

auto sum_float = sum(2.0f, 1.1f,2,3,6.0f,0.75, static_cast<double >(5.0 + 1e-12));
std::cout<<"Sum; var sum_float: "<<sum_float<<std::endl;
std::cout<<"Type of sum_float: "<< typeid(sum_float).name()<<std::endl;

auto sum_double = sum(static_cast<double >(5.0 + 1e-12),2, 1.1f,2,3,6.0f,0.75);
std::cout<<"Sum; var sum_double: "<<sum_double<<std::endl;
std::cout<<"Type of sum_double: "<< typeid(sum_double).name()<<std::endl;

Ouput:

Sum; var sum_int: 19
Type of sum_int: i
Sum; var sum_float: 19.100000381469727
Type of sum_float: f
Sum; var sum_double: 19.000000000001002
Type of sum_double: d

Yes, we was be correct, output result will be casted to first value!

Also we can define constructor with variadic templates, and create something cool! Like this :

Value and sum derived from value_base

VALUE_BASE is a just interface, VALUE and SUM override from them. So VALUE and SUM have function getVal. Now we can easily build hierarchic expression evaluator, actually, I am not sure about this title.

Code:

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

/*
 * Everything has value, base class for those classes who are so good at
 */
class VALUE_BASE{
public:
    /**
     * Get value
     * @return int value
     */
    virtual int getVal() = 0;
    virtual ~VALUE_BASE() = default;

    operator int(){
        return this->getVal();
    }
};


/**
 * We check if type U is base of VALUE_BASE
 * @tparam U type which will be checked.
 */
template <typename U>
void is_base_of_valuebase_assert(){
    static_assert(std::is_base_of<VALUE_BASE, U>::value, "Type is not instance of VALUE_BASE");
}
/**
 * We if type U and V is base of VALUE_BASE
 * @tparam U type which will be checked.
 * @tparam V type which will be checked.
 */
template <typename U, typename V>
void is_base_of_valuebase_assert(){
    static_assert(std::is_base_of<VALUE_BASE, U>::value, "The first argument must be a base class of VALUE_BASE");
    static_assert(std::is_base_of<VALUE_BASE, V>::value, "Second argument must be a base class of VALUE_BASE");
}
/**
 * VALUE - class which derived, contain value, and implement function getVal
 */
class VALUE:public VALUE_BASE{
int value;
public:
    /**
     * Get stored value
     * @return current value
     */
    virtual int getVal() override {
        return this->value;
    }


    virtual ~VALUE() override {
        std::cout<<"destroying VALUE object, which contains :"
                 <<this->getVal()<<" as value."<<std::endl;;
    }

    /*
     * We delete this class couse we useonly moving operations!
     */
    VALUE(const VALUE &vval) = delete;

    /*
     * Default move and move assigment contructors
     */
    VALUE(VALUE&& v ) {
        this->value = std::move(v.value);
        v.value = -1;//we cannot destroy passed object, so set it into -1
        std::cout<<"moving VALUE object, which contains :"
                 <<this->getVal()<<" as value" <<std::endl;
    }
    VALUE&operator =(VALUE&&) = default;
    /*
     * store passed int value
     */
    VALUE(const int & val){
        this->value = val;
        std::cout<<"creating VALUE object, which contains :"
                 <<this->getVal()<<" as value."<<std::endl;;

    }
};

/*
 * Calculate sum of objects
 * Store multiple references , which direct to classes whose implement getVal function
 */

class SUM: public VALUE_BASE{
private:

    template <typename T_VALUE>
    void init(T_VALUE&& value){
        is_base_of_valuebase_assert<T_VALUE>();

        this->sum_arguments.push_back(std::make_shared<T_VALUE>(std::move(value)));
    }
    template <typename T_VALUE, typename... Args>
    void init(T_VALUE&& value, Args&&... rest){
        is_base_of_valuebase_assert<T_VALUE>();
        this->sum_arguments.push_back(std::make_shared<T_VALUE>(std::move(value)));
        init(std::move(rest)...);
    };
public:
    std::vector< std::shared_ptr<VALUE_BASE> > sum_arguments;

    void log(std::string operation){
        std::cout << operation<<" SUM object, which contains :";

        int value_counter = 0;
        for(auto& v: this->sum_arguments){
            std::cout<<(v == nullptr? "nullptr": std::to_string(v->getVal())) << " as "<< std::to_string(++value_counter) <<" value, ";
        }
       std::cout<< std::endl;
    }

    virtual ~SUM(){
            log("destroying");
    }

    /**
     * Move data from data which was be passes as rvalue, to our std::vector of refferences.
     * @tparam T_VALUE1 should be derived from VALUE_BASE
     * @param value1 value which will be used as arguments for sum
     */
    template <typename T_VALUE1>
    SUM(T_VALUE1&& value){
        is_base_of_valuebase_assert<T_VALUE1>();
        this->init(std::move(value));

        this->log("creating");
    };

    template <typename T_VALUE, typename... Args>
    SUM(T_VALUE&& value, Args&&... rest){
        this->init(std::move(value), rest...);

        this->log("creating");
    };

    SUM(const SUM&) = delete;

    SUM(SUM&& sum){
        //Shared ptr = works like std::move
        this->sum_arguments = std::move(sum.sum_arguments);

        this->log("moving");

    }

    /**
     * Calculate sum
     * @return sum
     */
    virtual int getVal() override {
        return std::accumulate(this->sum_arguments.begin(), this->sum_arguments.end(), 0,
        [](const int&a, auto& value){
            return a + value->getVal();
        });
        
    }

};

int main(){
    //Wow we can make something like this!
    auto sum = SUM{
            VALUE{10}, //First argument derived from VALUE_BASE
            SUM{       //SUM also derived from VALUE_BASE
                    VALUE{5},
                    VALUE{11}
            }
    };
    std::cout<<"SUM = "<<sum.getVal()<<std::endl; //will be printed 26
}

Will be printed:

1. creating VALUE object, which contains :10 as value.
2. creating VALUE object, which contains :5 as value.
3. creating VALUE object, which contains :11 as value.
4. moving VALUE object, which contains :5 as value
5. moving VALUE object, which contains :11 as value
6. creating SUM object, which contains :5 as 1 value, 11 as 2 value, 
7. moving VALUE object, which contains :10 as value
8. moving SUM object, which contains :5 as 1 value, 11 as 2 value, 
9. creating SUM object, which contains :10 as 1 value, 16 as 2 value, 
10. destroying SUM object, which contains :
11. destroying VALUE object, which contains :-1 as value.
12. destroying VALUE object, which contains :-1 as value.
13. destroying VALUE object, which contains :-1 as value.
14. SUM = 26
15. destroying SUM object, which contains :10 as 1 value, 16 as 2 value, 
16. destroying VALUE object, which contains :10 as value.
17. destroying SUM object, which contains :5 as 1 value, 11 as 2 value, 
18. destroying VALUE object, which contains :5 as value.
19. destroying VALUE object, which contains :11 as value.

Let’s take a look at the output, firstly we creating a VALUE leafs (lines 1-3). Moving leafs 5 and 11 into SUM object (4-6). Moving value and SUM object into the second sum(main sum) lines 7 - 10. After we see how all variables which were rhs are destroyed(10-13). Get result at line 14. And after that will be destroyed all object sum in the main function, cause function is destroyed.

But we can create a cool concept language which will look like this:

auto Fib = FUNC{
	NAME{
			"fibonaci"
	},
	ARGS{
			ARG<int>("first",0),
			ARG<int>("second", 1),
			ARG<int>("n", 10)
	},
	BODY{
		VAR{
			"SUM",
			PLUS("first", "second")
		},
		VAR{
			"N",
			MINUS("n", 1);
		},
		RETURN{
			IF{
				EQUAL{"N", 1},
				1
			},
			ELIF{
				EQUAL {"N", 2},
				1
			},
			ELSE{
				CALL_FUNC("fibonaci", "second", "SUM", "N")
			}
		}
	}
}
std::cout<<Fib()<<std::endl;

We create an object function for calculation fibonacci number, this object/function has a name, input arguments, and body. In the body, we define variables, makes some calculation, return value which depends on some condition or returns result of recursion call. Actually, by using this approach, we can implement more coolest algorithms like quick sort, or declare recursive data structures like trees. Yes, we will try to implement this function in next blog post!