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
}