Introduction to C++ 11 Series – Part 7, decltype, auto (again) and Trailing Return Types

March 28, 2013

There is a joke, were a guy asks his friend, “Do you know what this is?” Doing some sort of wave shape movement with his hand. When his friend answers, “I don’t know”, the guy replies, “I don’t know either, but here comes another one like this!”

decltype is, like the joke says, “another one like this”. It provides a way to use the type of an expression in any place that a type can be used:

  • Declare a variable where the type of a given expression defines its type.
  • Declare a function where its return type is defined by a given expression.
  • auto, decltype & trailing return types (to be discussed shortly) are template library development enablers.

//This can be more properly rewritten using std::forward<T> and r-value references.

template <typename T, typename S>

auto add(const T& t, const S& s) -> decltype(t+s)

{

       return t+s;

}

 

void decl_type()

{

       float arr[15];

       decltype(arr) another_arr = {1,2,3};

       decltype(arr[0]) a_float_ref = arr[9];//float&

       decltype(arr[1]+7) a_float = 42.0f;//float

 

       decltype(rand()) number = rand();

 

       Complex i = { 0.0, 1.0 };

       const Complex* j = &i;

       decltype(i.real) real_val = 16.0;//double

       decltype((i.real)) real_val_ref = i.real;//double&

       real_val_ref++;

       decltype((j->imag)) imag_val_ref = j->real;//const double&

       decltype(j->imag) imag_val = j->imag;//double

       imag_val++;

       cout << i << endl;

 

       decltype(add(1,3.14)) sum = add(1,3.14);

       auto str = add(string("Goodbye, old "),‘C’);

       cout << sum << ‘ ‘ << str << endl;

}

 

The result is:

clip_image001

 

To see the real types, lets use the typeid_of function from the sample in the post about auto:

template <class T> void typeid_of(T &&t, const string &msg)

{

            cout << msg << ‘:’ << endl;

            cout << "Typeid: " << typeid(t).name() << endl;

            if (is_volatile<T>::value) cout << "volatile" << endl;

            if (is_const<T>::value) cout << "const" << endl;

            if (is_pointer<T>::value) cout << "pointer" << endl;

            if (is_reference<T>::value) cout << "reference" << endl;

            cout << endl << endl;

}

 

struct Complex

{

            double real;

            double imag;

            double abs_plus(double d) { return sqrt(real*real+imag*imag)+d; }

};

ostream& operator<<(ostream& os, Complex& c)

{

            os << c.real << ‘ ‘ << c.imag;

            return os;

}

 

template <typename T, typename S>

auto add(const T& t, const S& s) -> decltype(t+s)

{

            return t+s;

}

 

void show_types()

{

            float arr[15];

           

            decltype(arr[0]) a_float_ref = arr[9];//float&

            typeid_of(forward<decltype(a_float_ref)>(a_float_ref), "decltype(arr[0]) a_float_ref");

           

            decltype(arr[1]+7) a_float = 42.0f;//float

            typeid_of(forward<decltype(a_float)>(a_float), "decltype(arr[1]+7) a_float");

 

            decltype(rand()) number = rand();

            typeid_of(forward<decltype(number)>(number), "decltype(rand()) number");

 

            Complex i = { 0.0, 1.0 };

            const Complex* j = &i;

            decltype(i.real) real_val = 16.0;//double

            typeid_of(forward<decltype(real_val)>(real_val), "decltype(i.real) real_val");

           

            decltype((i.real)) real_val_ref = i.real;//double&

            typeid_of(forward<decltype(real_val_ref)>(real_val_ref), "decltype((i.real)) real_val_ref");

           

            real_val_ref++;

            decltype((j->imag)) imag_val_ref = j->real;//const double&

            typeid_of(forward<decltype(imag_val_ref)>(imag_val_ref), "decltype((j->imag)) imag_val_ref");

           

            decltype(j->imag) imag_val = j->imag;//double

            typeid_of(forward<decltype(imag_val)>(imag_val), "decltype(j->imag) imag_val");

           

            imag_val++;

            cout << i << endl;

           

            decltype(add(1,3.14)) sum = add(1,3.14);

            typeid_of(forward<decltype(sum)>(sum), "decltype(add(1,3.14)) sum");

           

            auto str = add(string("Goodbye, old "),‘C’);

            cout << sum << ‘ ‘ << str << endl;

}

 

The result is:

clip_image001[4]

 

Trailing Return Type

Look at the declaration of the Add template function from the last example:

template <typename T, typename S>

auto add(const T& t, const S& s) -> decltype(t+s)

{

       return t+s;

}

 

The return expression should be the type of the result expression of the operator + that adds a variable from type T and a variable from type S. We do not know the type of this expression, but we can use the decltype to get it. The problem is that we cannot use the variable t and s before we declare them in the function prototype. With the help of auto and trailing return type, we can solve this problem.

Trailing return type can be used with any function or method. You can declare a function return type as an auto and add the return type at the end of the prototype with the use of the arrow
(->). As in the case of regular function return type, if you declare a trailing return type and return a value that has a different type, the compiler will try to convert the value to the trailing-return-type type.

In lambda functions (I will write about them in the next post), in the case of more than one return point, you must use the trailing return type syntax.

You can read more here.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

one comment

  1. MichaudMay 9, 2013 ב 00:26

    With havin so much written content do you ever run into any
    problems of plagorism or copyright infringement?
    My site has a lot of unique content I’ve either authored myself or outsourced but it looks like a lot of it is popping it up all over the web without my agreement. Do you know any solutions to help reduce content from being ripped off? I’d
    definitely appreciate it.

    Reply