Wednesday, December 5, 2012

Using Algorithm Library and Functional

Just an example to show the utility of the library algorithm.

#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>

using namespace std;

int op_increase (int i) { return ++i; }
int op_sum (int i, int j) { return i+j; }

void inc(int& val){
    static int i = 0;
    val += i;
    i += 10;
}

ostream& operator<<(ostream& out, const vector<int>& a){
    for (int i = 0; i < a.size(); i++)
        out << a[i] << ", ";
    
    out << endl;
    return out;
}
int main () {
  vector<int> first(5);
  vector<int> second;
  vector<int> result;
  
  second.resize(first.size());    
  result.resize(first.size());

  // set some values:
  for_each(first.begin(), first.end(), inc); 
  for_each(second.begin(), second.end(), inc);
  
  cout << first << second << result;

  transform (first.begin(), first.end(), result.begin(), op_increase);
  cout << result;
  
  transform (first.begin(), first.end(), second.begin(), result.begin(), op_sum);
  cout << result;

  vector<int> lenghts;
  vector <string*> numbers;

  // populate vector of pointers:
  numbers.push_back ( new string ("one") );
  numbers.push_back ( new string ("two") );
  numbers.push_back ( new string ("three") );
  numbers.push_back ( new string ("four") );
  numbers.push_back ( new string ("five") );

  lenghts.resize(numbers.size() );

  transform (numbers.begin(), numbers.end(), lenghts.begin(), mem_fun(&string::length) );
  cout << lenghts;

  system("pause");
  return 0;
}

Also, it is possible to use mem_fun_ref instead of mem_fun without the need of use a vector of pointers to strings and just use strings instead of,

Thus, in conclusion, it's very interesting to know how to use this libraries because allow you to work more efficiently and do the same work in less time.

Sunday, December 2, 2012

Pointers, References and Local Variables

Well, I bring here an example when you should figure out how constructors, pointers and reference works.

Thus, here it goes:

Note: Take a fast look to A class and start reading in main function.

#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;

class A{
private:
    int a;
public:
    A() : a(-1){
        cout << "Default constructor" << endl;
    }
    A(int val) : a(val){
        cout << "Calling contructor by int" << endl;
    }
    //************************************
    A(A* val){
        cout << "Calling contructor by A_pointer" << endl;
        a = val->get();
    }
    A(A& val){
        cout << "Calling contructor by A_reference" << endl;
        a = val.get();
    }

    // This can't be done because when the constructor is called
    // the parameter of the function calls itself, I mean, val is being
    // a local variable
    /*A(A val){
        a = val.get();
    }*/

    int get(){ return a; }
    int get() const { cout << "get 'a' by a const variable\n"; return a; }
    int& getRef(){ return a; }
    //int& getRef() const{ return a; } This can't be done
};


void byPointers(A *a, A *b){
    *a = b->get()*2; //(-1 * 2 = -2)
    // this can be done because a points to a instanced class A
    // in case that would point to null this would be a segmentacion fault
    // on runtime

    // Beside, this calls the constructor by value
}

void byReference(A& a, const A& b){
    a.getRef() = 1000; // we change a_int value, because a is a reference and a.getRef return the atribut inside the class by reference
                       // if the int atribut would've been public that would be equivalent to a.a = 1000;

    //so, because in this call, a and b are A_value, if we change a, also are changing b, let's look:
    cout << b.get() << endl;

    //However, we can't change the b value, because is constant although points to the same variable
}
void byReference2(A& a){
    a.getRef() = 1000000;
}

void byCopy(A a){
    cout << "a: " << a.get() << endl;

    a = A(25); 
    cout << "a: " << a.get() << endl; // now it's 25

    a.getRef() = 26;
    cout << "a: " << a.get() << endl; // now it's 26 but still being
    // a local variable
}

int main(){
    cout << "First example:" << endl;
    A A_value; // this calls default constructor
    
    cout << A_value.get() << endl;
    A* A_pointer; // this doesn't because is a pointer
    A_pointer = &A_value; // this doesn't call any A constructor
    *A_pointer = A_value; // this is equivialent to the previous line
    cout << A_pointer->get() << ", " << (*A_pointer).get() << endl << endl; // point to A_value (two ways to access it)
    //**************************************************************************************

    cout << "Second example:" << endl;
    byPointers(&A_value,&A_value); // this doesn't call any constructor
    // just points to the references of A_value, so inside the function 
    // if we change A *a, A *b pointers we'll change A_value
    cout << endl;

    // This is a bit obfuscated, so peruse
    byCopy(A_value); // byCopy expect to creat (A a) as a local variable
                     // so calls A_reference, or method to copy a class
                     // however, the construtor is by reference, a still be
                     // a local variable
    cout << A_value.get() << endl << endl;// Thus, we haven't changed any attribut of A_value
    //**************************************************************************************
    
    cout << "Third example:" << endl;
    byReference(A_value, A_value); // pass by reference doesn't call any constructor
                                   // because a and b are exactly A_value
    // So, after the call, A_value have changed:
    cout << A_value.get() << endl;

    // even, we can do the same with the pointer
    byReference2(*A_pointer);
    // and because A_pointer points to A_value, this will also change the value
    cout << A_value.get() << endl; 

    system("pause");
    return 0;
}

Friday, November 30, 2012

Example of two and three dimensional pointers

Welcome everyone,
I did a little problem to practice with pointers to other pointers. In this case, I did a matrix and pass it by a function than expect the reference of it.

The example compute the multiplication of two matrices.

Note: This post was inspired answering that post: http://www.cplusplus.com/forum/general/86553/


Enjoy it:


#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;

void fill(int& value){
    static int val = 0;
    val++;

    value = val;
}

void zero(int& value){
    value = 0;
}


void mult(int* **A,int* **B,int* **result, const int SIZE) {
    for (int i = 0; i < SIZE; i++)
        for (int j = 0; j < SIZE; j++)
            for (int k = 0; k < SIZE; k++)
                (*result)[i][j] += B[0][i][k] * (*A)[k][j];
}

int main(){
    int *vector;
    const int SIZE = 3;

    //reserve memory:
    vector = (int*) malloc(sizeof(int) * SIZE);
    for_each(vector,vector + SIZE,fill); //fill

    //print
    for(int i = 0 ; i < SIZE ; i++)
        cout << vector[i] << ", ";
    cout << endl << endl << endl;

    //reserve memory for a pair of matrices:
    int**matrix;
    matrix = (int**) malloc(sizeof(int*) * SIZE );
    for(int i = 0 ; i < SIZE ; i++ )
        matrix[i] = (int*) malloc(sizeof(int) * SIZE);

    int**result;
    result = (int**) malloc(sizeof(int*) * SIZE );
    for(int i = 0 ; i < SIZE ; i++ )
        result[i] = (int*) malloc(sizeof(int) * SIZE);
    //***************************

    //fill matrix:
    for_each(matrix[0],matrix[0] + SIZE,fill);  for_each(result[0],result[0] + SIZE,zero);  
    for_each(matrix[1],matrix[1] + SIZE,fill);  for_each(result[1],result[1] + SIZE,zero);
    for_each(matrix[2],matrix[2] + SIZE,fill);  for_each(result[2],result[2] + SIZE,zero);

    //print it
    for(int i = 0 ; i < SIZE ; i++){
        for(int j = 0 ; j < SIZE ; j++)
            cout << matrix[i][j] << ", ";
        cout << endl;
    }
    cout << endl << endl << endl;

    mult(&matrix, &matrix, &result, SIZE);
    //print it
    for(int i = 0 ; i < SIZE ; i++){
        for(int j = 0 ; j < SIZE ; j++)
            cout << result[i][j] << ", ";
        cout << endl;
    }
    cout << endl << endl << endl;

    system("pause");

    return 0;
}

Sunday, November 25, 2012

Type Traits 2

Have I ever spoken about decltpe?
Well, I just mentioned.

In a previous post, I spoke about Type Traits. Now, I'm going further and show you some details about decltype; a new feature of C++11.

This is useful because you will spend less time having to write out things the compiler already knows.
C++11 introduces several tools for type inference. Decltype, auto, new return feature, these are some examples.

In this chapter, I'll review references and introduce decltype.
Read carefully and note the types.


#include <iostream>

using namespace std;

int main(){
    int a = 2, *b;
    b = &a;

    int& c = a; //int referenced
    c = 20; //This modifies a


    auto d = c; // that's an int, isn't referenced
    d = -1;

    decltype(c) e = a; // that's a referenced int
    e = -20;

    cout << a << ", " << c << ", " << *b << ", " << d << endl; // all refers to the same number
    //*****************************************************

    int q1 = 0;
    decltype(q1) q2 = 1;
    decltype( (q1) ) q3 = q1;// int&
    q3 = 2;

    cout << q1 << ", " << q2 << ", " << q3 << endl;
    //*****************************************************
    struct MyClass { double x; };
    const MyClass* const f = new MyClass(); // constant pointer pointing to constant value
    decltype( f ) asd = new MyClass(); // const MyClass* const so have to be initialized
    decltype( f->x ) x; // double
    decltype( (f->x) ) y = x; // const double&

    return 0;
}

Notice that decltype( (variable) )  with double parenthesis is referenced. 


Now, I want to introduce a new way to declare function. 
The idea:
template <typename Builder>
auto
makeAndProcessObject (const Builder& builder) -> decltype( builder.makeObject() )
{
    auto val = builder.makeObject();
    // do anything
    return val;
}
A short example:
#include <iostream>
#include <utility>

using namespace std;

class A{
public:
    typedef pair<int,int> T;

    static T build(){
        return T(1,2);
    };
    static ostream& printA(ostream& out,const T& val){
        out << "( " << val.first << ", " << val.second << " )" << endl;
        return out;
    };
    // we can override the operator <<
    // inside the class
    //
    // friend ostream& operator<<(ostream& out, const A& val)
    //
    // but we don't want to print an A class, we just are printing an
    // internal type
};

// NEW C++11
auto foo() -> decltype( A::build() ){
    auto a = A::build();
    
    // DO ANITHING

    return a;
}

ostream& operator<<(ostream& out,const A::T& val){
    return A::printA(out, val); // overloading << operator for cout << A::T
}

int main(){
    cout << foo() << endl;
    // If we change A::T class and build constructor, foo() will change automaticaly the return type

    return 0;
}

Thursday, August 30, 2012

A-star Search

Hello Folks,
Today I won't write code but instead of I'll speak about a famous algorithm to find optimal paths.

A* search

It evaluates nodes by combining g(n) and h(n), where g(n) is the cost to reach the current node and h(n) is the heuristic cost from the note to the goal.

So, by combining both we have f(n) that is the estimated cost of the cheapest solution.
This algorithm is both complete and optimal whether satisfies certain heuristic conditions.
In fact, the algorithm is identical to Uniform-Cost-Search, also known by the name Dijkstra, except that uses g(n) + h(n) instead of g(n).


Conditions for optimality

The main condition we require for optimality is that h(n) has to be an admissible heuristic. An admissible heuristic is one that never overestimates the cost to reach the goal.

In other words, g(n) is the minimal accumulated cost from the initial state to the current node and h(n) is heuristic cost from the current node to the goal. Thus, f(n) that is g(n) + h(n) is the cost from the initial state to the goal.
So, admissibility here means that h(n) has to be calculated heuristicly and this means that won't be the real cost.

So, if h(n) is bigger that h*(n), which is the real cost or the perfect heuristic, then f(n) = g(n) + h(n) would be bigger than the shortest path and due to wouldn't be optimal.

An example of an admissible heuristic is the straight-line distance h_SLD. Whether we want to calculate the shortest path between two cities h_SLD will be an excellent heuristic to be used because between two points always the shortest path is a straight-line and don't exist a better solution. Thus, this heuristic will be admissible because would never calculate a further path than the optimal solution.


A*: Additional Properties

A* store in memory all nodes visited so his complexity is exponential both time and space.
Thus, A* is not practical for many large-scale problems. There are, algorithms, that overcome the space problem without sacrificing optimality or completeness, at a small cost in execution time.
For instance, IDA*.

A* is optimal in another sense: no other algorithm expands less nodes than A* with same heuristic function but this doesn't mean that A* is always the fastest.
Another property is that better heuristic functions A* expands less nodes.

0 < h_1 < h_2 < h* 

With h_2 will expand less nodes than with h_1.


Example of heuristics

I won't explain any of it but just with the name you will be able to google it.

  • Manhattan distance in N-puzzle
  • Euclidean Distance in Routing Finding
  • Spanning Tree in Travelling Salesman Problem
  • Shortest Path in Job Shop Scheduling


Algorithm


Illustration of A* search for finding path from a start node to a goal node.

Extracted from wikipedia.










Example:


In order to solve the shortest path in the graph using A* I will use two list, one for the current nodes ( search frontier ) and another for the visited nodes ( in order to check loops ).

Opened

1                                  2                                3                               and so on
f(a) = 1.5 + 4 = 5.5       f(b) = 3.5 + 2 = 5.5      f(c) = 6.5 + 2 = 8.5
f(d) = 2 + 4.5 = 6.5       f(d) = 2 + 4.5 = 6.5      f(d) = 2 + 4.5 = 6.5


Closed
1                                  2                                3
                                    f(a)                            f(a)
                                                                     f(b)

Saturday, May 19, 2012

Random vector

Last post it was about lambdas but, indeed, I just focused with an utility; random vectors creation. Now, after still being researching I found more intuitive and elegant forms.

Let's see this amazing things:



#include <algorithm>
#include <iostream>
#include <vector>
#include <time.h>

//Start reading inside main!!!!
//first template is the rank of numbers we want
//second, where it starts
template<int N, int Start = 0>
class MyRand{
public:
     int operator()(void){
         return std::rand()%N + Start;
     }
};

int fRand(){
     return std::rand()%10 + 30;
}

int main()
{
      // Create a vector object that contains 10 elements.
      std::vector<int> a(10);

     // randomly initialize using lambda expressions
     srand((unsigned)time(0)); 

     //generating the vector by means of standard random function
     //This is nice but you don't have much control of which rank of numbers
     //will be returned. Indeed, you know, with the macro RAND_MAX
     //and this is a huge number.

     //And that perhaps isn't what we expected. So the solucion is to use
     //a custom function:
     std::generate(a.begin(), a.end(), std::rand );

     //Now, just changing fRand we can get our wished numbers, but
     //even that is not the best way because you can't use any function
     //that takes some parameter and then you'd need as many function
     //as you need; and that can be tedious. Instead of this, we can use templates
     //which we won't get that problem.
     std::generate(a.begin(), a.end(), fRand );

     //So, here we go:
     //With two templated parameters we can get any random rank of numberes we want.
     //for example, if we want numbers between 10 and 20 that's the example:
     std::generate(a.begin(), a.end(), MyRand<10,10>() );

     //O maybe we want numbers between 14 and 71
     //how many numbers there are between them? 71 - 14 = 57 and we start at 14
     //So:
     std::generate(a.begin(), a.end(), MyRand<57,14>() );


     //like last time, how to write this vector with just code a line
     std::for_each(a.begin(), a.end(), [](int a){ std::cout << a << std::endl; } );
     return 0;
}


Sunday, May 13, 2012

Lambdas

Yes, I'm still alive hehe
Today, I have been working with C++11 and I did some awesome things.

In this post, I won't explain much, just because I'm still inexperienced but I will.

How many times did you print a vector? And how many lines was needed? Yes, of course. You could make a function but so many times you are just debuging and you aren't really interested with it because you are solving anothers problems of mayor importance.

Here, there's an example with one line to do it. Moreover, I randomly initialized the vector with the same idea.

#include <algorithm>
#include <iostream>
#include <vector>
#include <time.h>

using namespace std;

int main()
{
    // Create a vector object that contains 10 elements.
    vector<int> a(10);

    // randomly initialize using lambda expressions
    srand((unsigned)time(0)); 
    for_each(a.begin(), a.end(), [](/*by reference*/ int& aux){
        aux = rand()%100; } );

    //now, print it
    for_each(a.begin(), a.end(), [](int aux){ cout << aux << endl; } );

    return 0;
}


If you are not used to use for_each, here is an example without use lambdas:

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

void printThing(int i){
     cout << i << endl;
}

int main(){
    // Create a vector object that contains 10 elements.
    vector<int> a(10);

    // randomly initialize using lambda expressions
    srand((unsigned)time(0)); 
    for_each(a.begin(), a.end(), [](int& aux){aux = rand()%100; } );

    for_each(a.begin(), a.end(), printThing );
    return 0;
}


And another example using templates, just getting fun:

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

template<class T>
void printThing(T i){ //void printThing(const T& i) would be better/faster
     cout << i << endl;
}

int main(){
    // Create a vector object that contains 10 elements.
    vector<int> a(10);

    // randomly initialize using lambda expressions
    srand((unsigned)time(0)); 
    for_each(a.begin(), a.end(), [](int& aux){aux = rand()%100; } );

    for_each(a.begin(), a.end(), printThing<char> );//yes is char, 
    //just to show that we are casting
    return 0;
}

Thursday, March 29, 2012

Playing with variadic

Okey, here's an example with variadics. Of course, that's not ever the best way, in fact, it's absolutely bad practice but I was just playing with.

So, if you are interested in what this guy did? go ahead if not and you want to learn and even use
some of my ideas, don't try it.

Being weighed, this is not a good example, just take it for fun.


#include <iostream>

template<typename...Types>
class List{
public:
     int size;
     void** elements;//aray of things
     List(){
         size = sizeof...(Types);
     };
     List(Types... Args){
         size = sizeof...(Types);
         elements = new void*[size];
         if(size != sizeof...(Args) )
             std::cout << "diferent size" << std::endl;
         else{
             std::cout << "good" << std::endl;
             push(0,Args...);
         }
     };
    
private:
     template<class T>
     void push(int pos, T last){
         if(pos == size-1){
             std::cout << "at: " << pos << " added -> " << *last << std::endl;
             std::cout << "All correct" << std::endl;
             elements[pos] = static_cast<void*>(last);
         }
     }
     template<class First, class...Rest>
     void push(int pos, First first, Rest...rest){
         elements[pos] = static_cast<void*>(first);
         std::cout << "at: " << pos << " added -> " << *first << std::endl;
         pos++;
         push(pos,rest...);
     }
};

using namespace std;

struct A{
public:
      string info;
public:
      A(string in) : info(in){};
      friend ostream& operator<<(ostream& out, const A& a){
          out << a.info;
          return out;
      };
};
int main(void){
     List<int*,int*,double*,string*,A*> list(new int(1),new int (2),
                     new double (2.101), new string("aloha"),new A("NICE") );

     cout << "size: " << list.size << endl;
     cout << *static_cast<int*>(list.elements[0]) << ", ";
     cout << *static_cast<int*>(list.elements[1]) << ", ";
     cout << *static_cast<double*>(list.elements[2]) << ", ";
     cout << *static_cast<string*>(list.elements[3]) << ", ";
     cout << *static_cast<A*>(list.elements[4]) << ", ";
     
     return 0;
}

Output:


good
at: 0 added -> 1
at: 1 added -> 2
at: 2 added -> 2.101
at: 3 added -> aloha
at: 4 added -> NICE
All correct
size: 5
1, 2, 2.101, aloha, NICE,

Wednesday, March 28, 2012

Variadic templates

Every time, every time, C++ surprise me. Today, with variadic templates that allow us to specifier an unknown number of arguments. And this becomes an completely useful tool.

At the moment, I won't explain it because still being a mystery for me. Just say that this allow recursion
like prolog. Moreover, we can make containers of different types and even very things that I don't know.

Here's my example:


#include <iostream>

using namespace std;

//base case:
template<class T>
void printArray(T last){
     cout << last << endl;
}

template<class First, class...Rest>
void printArray(First first, Rest... rest){
     cout << first << ", ";
     printArray(rest...);
}

struct A{
public:
     string info;
public:
     A(string in) : info(in){};
     friend ostream& operator<<(ostream& out, const A& a){
         out << a.info;
         return out;
     };
};

int main(void){
     printArray(1);
     printArray(1,2);
     printArray(1,2,3);
     printArray(1,2,3,4,5);
     
     printArray("I");
     printArray("I","can't");
     printArray("I","can't","that");
     printArray("I","can't","that","this");
     printArray("I","can't","that","this","works");
     
     //diferent types, even a custom class
     printArray(1,"aloha",2.123,'a', A("Com estas?") );
     
     return 0;
}

Output:



1, 2, 3
1, 2, 3, 4, 5
I
I, can't
I, can't, that
I, can't, that, this
I, can't, that, this, works
1, aloha, 2, que tal?
1, aloha, 2.123, a, Com estas?



String arguments in templates

Well, well, well.
Up to this point, you should have a minimal idea of templates. Of course, there are some chapter
that you didn't understand yet or you didn't take the whole idea that I was trying to teach.

But don't worry, you just need reviews like this post to understand that some of the titles I made
are of huge interest and even, indeed, more complex.

Here there's an example that show that the chapter, argument deduction, is more complex as it
seems and we don't have to take it as if nothing because even with the string type we can get
much mistakes as you think.

#include <string>
// note: reference parameters
template <typename T>
inline const T& max (const T& a, const T& b){
     return a < b ? b : a;
}
int main(){
     std::string s;
     ::max("bye","cya"); // OK: same type
     ::max("hello","bye"); // ERROR: different types
     ::max("chau",s); // ERROR: different types
}


First look, you may think, what the hell is happening here, how it doesn't work?, but if you take long
time and read the compiler you'll that is an error about types.

First off, remember that string is a C++ type and when you declare some thing like "this (with commas)" you are not really creating an string if not that is an char*. Thus, max(), is not
calling the function max with string's type if not that are char's.

Beside, we have to notice, in order to see the error, that the problem becomes from pass arguments
as reference (&) because without this we didn't get error from first and second call.
That's it because without pass by reference the type pass it is const char*. On the other hand, calling
by reference, we are passing the following type. char const[3] where this number is the size of
the string.

This makes that two strings of different sizes makes an error like in the second call where
"hello" is 4 and "bye" is 3(insist, all this is by argument deduction).

There are many forms to solve this problem like be sure that strings are strings(for instance, string("bye") ) but I want to handle it with templates; it's not as elegant as I'd like but this is it.


template <typename T, int N, int M>
inline T const* max (const T (&a)[N], const T (&b)[M]){
     return a < b ? b : a;
}




Friday, March 23, 2012

Type Traits

Hello everybody,
Lately I have been snowed under work, in fact, I still. But I'm posting anyway ^ ^

Well, here's an introduction to some features of templates type traits.

Notice that this post is just an introduction and if you don't see the utility now you will see in further posts. Just say that generic programming can sometimes be not generic enough.

Starting to take a look to the standard way to check types of variables.

The standard provide some ways to do it. Although has his limitations and even isn't much effective but
allows to compare or even read the type of variables.

Doing this task I'm using typeid that return a std::type_info where is implemented some
methods like name in order to return a human-readable.

I don't know why my compiles expres int as i, I think that is not much normal because I have seen
many examples where typeid().name return the word int, not i, but in fact don't care.


// type_info example
#include <iostream>
#include <typeinfo>
using namespace std;

struct Base {};
struct Derived : Base {};

//using virtual; being polymorphic
struct Poly_Base {virtual void Member(){}};
struct Poly_Derived: Poly_Base {};

int main() {
     int i;
     int *p_int = 0;
     double array_d[10];

     cout << "    int is: " << typeid(int).name() << endl;
     cout << "      i is: " << typeid(i).name() << endl;
     cout << "  int==i? : " << boolalpha << 
           (typeid(i) == typeid(int)) << endl;
            //with boolapha we'll print true/false inside of 1/0
     cout << "  p_int is: " << typeid(p_int).name() << endl;
     cout << " *p_int is: " << typeid(*p_int).name() << endl;
     cout << "array_d is: " << typeid(array_d).name() << endl << endl;
   
     // non-polymorphic types:
     Derived derived;
     Base* pbase = &derived;
     cout << "derived is: " << typeid(derived).name() << endl;
     cout << "  pBase is: " << typeid(pbase).name() << endl;
     cout << " *pbase is: " << typeid(*pbase).name() << endl;
     cout << " same type? "; 
     cout << boolalpha <<( typeid(derived)==typeid(*pbase) ) 
          << endl << endl;

     // polymorphic types:
     Poly_Derived polyderived;
     Poly_Base* ppolybase = &polyderived;
     cout << "polyderived is: " << typeid(polyderived).name() << endl;
     cout << "  ppolybase is: " << typeid(ppolybase).name() << endl;
     cout << " *ppolybase is: " << typeid(*ppolybase).name() << endl;
     cout << boolalpha << "same type? " << 
           ( typeid(polyderived)==typeid(*ppolybase) ) << endl << endl;
}

Output:


    int==i? : true
    p_int is : Pi
  *p_int is : i
array_d is : A10_d

derived is : 7Derived
  pBase is : P4Base
 *pbase is : 4Base
 same type? false

polyderived is : 12Poly_Derived
   ppolybase is : P9Poly_Base
 *ppolybase is : 12Poly_Derived
        same type? true

Useful? Could be.
Although, as I said, it has some limitations, for example, what happens if I want to compare an
usigned int and an int, is it equal? The answer is no; false.

So, now, I want to show how we could do this task using temples. The behind idea is argument deduction and specialization.



#include <iostream>

template<class T>
struct is_int{
     static const bool value = false;
};
template<>
struct is_int<int>{
     static const bool value = true;
};
template<>
struct is_int<unsigned int>{
     static const bool value = true;
};
template<>
struct is_int<char>{
     static const bool value = true;
};

class A{};

using namespace std;

int main() {
     cout << "is int?: " << boolalpha << is_int<int>::value << endl;
     cout << "is unsigned int?: " << boolalpha 
          << is_int<unsigned int>::value << endl;
     cout << "is string?: " << boolalpha << is_int<string>::value << endl;
     cout << "is A?: " << boolalpha << is_int<A>::value << endl;
}

Output:


is int?: true
is unsigned int?: true
is string?: false
is A?: false

Finally, just say that boost library provide many of this template functions.


#include <boost/type_traits>


And even functions like:

is_pointer<T>
is_arithmetic<T>
is_function<T>
is_class<T>
is_polymorphic<T>
has_trivial_constructor<T>

Awesome, I know.


Also, I wanted to mention to the new decltype that is introduced in the new version of C++,
this one will be a tricky form to declare variables that you don't know how, because his complexity
can be complex like templates. It's not exactly related with what I explained but I think that
may be interesting to someone.

Monday, March 5, 2012

Pointers and Constants using Int

Hello everybody,

I did a short example to give an expression of pointers and constants. It's uniquely illustrative. With all this, I'm trying to lay the groundwork to const correctness's use because the good use of const is absolutely important in complex applications where the efficient matter.

Here we go:


int main(){
           int         intInt;
     const int         cint = 10;//we have to initialize here unless 
                                 that is an atribut's class
                                 //and, in this case, have to be 
                                 initialize inside the constructor
           int *       ptrInt;
     const int *       constValue;
           int * const constPtr = &intInt;//have to be initialize here
     const int * const constPtrValue = &intInt;//have to be initialize 
                                               here

     
     //intInt
     intInt = 1;
     intInt = 2;
     //we can change the value as times as we like
     
     //cint
     //cint = 2; EROR: this variable is const so is the same 
     to say read-only
     
     //ptrInt
     ptrInt = &intInt;
     //ptrInt = &cint; ERROR: the reference from cint is 'const int*' 
     and was expected int*
     *ptrInt = cint; //we can put the value of cint inside our pointer
                     //but in this case we have copied by value and no 
                     by reference so
                     //*ptrInt don't point to a const and then 
                     we can increment his value:
     (*ptrInt)++;    //now is 11
     
     //constant pointer
     constValue = &cint; //we can point to any constant int
     int aux = 20;
     constValue = &aux; //even to a int but still being unaccesible 
                        using constValue
     intInt = 30;
     int *auxPtr = &intInt;
     constVconstValue = auxPtr;//in this way the value of constValue is 30
                         //and still being unaccesible from constValue
     //*constValue = 12; ERROR: the value of constValue is const, 
     so *constValue is read-only
     intInt = 100;       //but we can change the value from the variable
                         //so this is legal, and then
     std::cout << *constValue;//this print 100
     
     (*auxPtr)++;        //but we still having access also from our auxPtr
                         //so this is legal to
     std::cout << *constValue;//and now, this print 101
     
     //int * const constPtr
     //constPtr = auxPtr; EROR: our pointer is constant so we can't change 
     the direction where point
     *constPtr = 2;//but the value isn't constant, so we can change it
     std::cout << *constPtr; // is 2
     std::cout << intInt;// and the value have been changed too, is 2
     
     //const int * const constPtrValue
     std::cout << *constPtrValue;// is 2 because we are pointing to intInt
     //constPtrValue = ptrInt; ERROR: assigment of read-only variable
     //*constPtrValue = 20; ERROR: read-only value
                 //so we only have access to the variable
                 //although we can change the value with other variables
     intInt = 666;
     std::cout << *constPtrValue; //this print 666
}