When to Use decltype in C++

decltype is usually meant to be wrapped in generic (template) library code and used only when strictly necessary. Outside of that, non-abusive auto is the day-to-day syntactic sugar.

1. What Is decltype

The name decltype is formed from “declare” and “type”, indicating that it is used to declare a type.

For details and usage, see the [decltype specifier] reference. In short, it extracts the type of a given expression and lets you use that data type to declare a new variable.

2. Differences from auto

Both can appear as type keywords when declaring variables, but the key differences are:

  1. Variables declared with auto must be initialized, because type deduction happens at compile time based on the initializer expression — the expression is also evaluated at runtime. decltype, on the other hand, already deduces the type from the expression without requiring initialization, and does not evaluate the expression’s value.
  2. Modifiers (such as const and references) are handled differently. However, due to C++’s ongoing patchwork of features, there are some exceptions that add complexity, which we won’t go into here.

These are only superficial differences. decltype is commonly found in template programming. For example, xinnjie’s implementation for compile-time detection of whether a class has a foo() method, as discussed in “Why does C++11 have decltype when it already has auto?”:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
//c++14
#include <experimental/type_traits> // for srd::experimental::is_de_detected
#include <iostream>
#include <type_traits>
template<typename T>
using has_foo_func = decltype(std::declval<T>().foo());

struct HasFoo {
    void foo() {}
};

struct NotHasFoo {
};

int main() {
    std::cout << "has foo" << std::experimental::is_detected<has_foo_func, HasFoo>::value << std::endl; // true
    std::cout << "has foo" << std::experimental::is_detected<has_foo_func, NotHasFoo>::value << std::endl; // false
}

B. Stroustrup presents more examples in the C++11 FAQ.

If you feel that auto and decltype overlap in functionality — I think they do. As stated in “A Brief Overview of auto and decltype in C++11”:

decltype was introduced to address some issues with auto. Anywhere you can use auto, you can use decltype. However, auto is more concise than decltype, so prefer auto when you can and fall back to decltype when you must.

In certain situations, decltype is the better choice. For instance, when you want y to always have whatever the declared type of x is.

When you want y to always have whatever the declared type of x is.

3. Summary

You shouldn’t be seeing or using decltype in “day-to-day” programming. It is most useful in generic (templated) library code, where the expression in question is not known and depends on a paramater. (By contrast, auto may be used generously all over the place.) In short, if you’re new to programming, you probably won’t need to use decltype for some time.

As noted in What is decltype and how is it used?: you shouldn’t be seeing or using decltype in “day-to-day” programming. It is most useful in generic (templated) library code, where the expression in question is unknown and depends on a parameter. (By contrast, auto may be used generously all over the place.) In short, if you’re new to programming, you probably won’t need to use decltype for some time.

References