If you don't pay attention to your money, others will.
GreaterThanZero.com


Page 5 of: C++ auto and decltype Explained, by Thomas Becker   about me  

The decltype Keyword: The Basics

Let's take another look at the example of the previous section, where we wrote a function template with two arguments whose precondition was that the product of the two arguments was defined. Inside the function, we declared a variable that could hold the product of the two arguments:
template<typename T, typename S>
void foo(T lhs, S rhs) {
  auto prod = lhs * rhs;
  //...
}
Now suppose that instead of declaring a variable whose type is that of the product of the arguments, we want to make a typedef for that type. Since the compiler knows what the type is, we should be able to do that. Before C++11, there was no official way of doing it. But some compilers had an extension keyword typeof for that purpose:
template<typename T, typename S>
void foo(T lhs, S rhs) {
  // Pre-C++11 compiler extension, now obsolete
  typedef typeof(lhs * rhs) product_type;
  //...
}
The purpose of decltype is to provide a standardized version of typeof. Since the result is not identical to the existing compiler extension typeof (and there were probably conflicting versions out there, I'm not sure), the term typeof could not be used. Instead, the previously unused term decltype was chosen. So in C++11, we can now write
template<typename T, typename S>
void foo(T lhs, S rhs) {
  typedef decltype(lhs * rhs) product_type;
  //...
}
Another situation where decltype comes in handy is when we want the return type of a function to be something that needs to be deduced from an expression. For example, let us try and modify the example above in such a way that it returns the product of its arguments. Naively, you would perhaps try this:
template<typename T, typename S>
// Does not compile: lhs and rhs are not in scope
decltype(lhs * rhs) multiply(T lhs, S rhs) {
  return lhs * rhs;
}
This won't compile because lhs and rhs are not in scope preceding the function name. To fix this, C++11 introduces what's called the trailing return type syntax:
template<typename T, typename S>
auto multiply(T lhs, S rhs) -> decltype(lhs * rhs) {
  return lhs * rhs;
}

This will compile and make the type of the product the function's return type. This is nothing to be intimidated by. It's just a bit of syntactic trickery to allow the compiler to grab the type of the expression lhs * rhs and make it the function's return type.

Note that the keyword auto that is used here is not the auto that we discussed in the previous three sections. The use of auto in this context just continues the time-honored practice of C and C++ to use the same lexical token for multiple purposes. Actually, I personally am a bit uncomfortable with the use of auto in this context. I'll tell you why later, after we have learned more about decltype.

When I had gotten this far in my studies of C++11, I was convinced that the following was a true statement, which it is not:

<wrong>
decltype deduces the type of an expression just like auto does. The difference is that decltype is applicable in a wider variety of contexts.
</wrong>

Read on to see just how wrong this is.