During the pre-C++11 era every variable, member, argument, etc. has to be explicitly typed. For example, if we were writing a template function operating on a range, how could we declare a variable of the type of its items?
template < typename InputIt, typename OutputIt, typename Predicate, typename Transform, > void transform_if (InputIt first, InputIt last, OutputIt out, Predicate& predicate, Transform& transform) { for (; first != last; ++first) { /* some_type */ v = *first; if (predicate(v)) { *out = transform(v); ++out; } } }
Getting the correct type to put in place of some_type was not obvious, and required a fair share of template metaprogramming. Now, with the decltype specifier introduced in C++11, the programmer can tell the compiler to use “the type of this expression”.
template < typename InputIt, typename OutputIt, typename Predicate, typename Transform, > void transform_if (InputIt first, InputIt last, OutputIt out, Predicate& predicate, Transform& transform) { for (; first != last; ++first) { decltype(*first)& v = *first; if (predicate(v)) { *out = transform(v); ++out; } } }
In the example above, decltype(*first) is the type of the result of dereferencing first.