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;
}

No comments:

Post a Comment