Channels ▼

Andrew Koenig

Dr. Dobb's Bloggers

A Note About decltype

July 27, 2011

Last week's article about C++0x left out a subtlety about decltype for space reasons: decltype is syntactically overloaded with two different, but related, meanings.

If n is a name (such as a variable or a class member), decltype(n) is the type that n is declared to have. If the declaration has a reference type, decltype(n) also has a reference type. For example:

int i;                // decltype(i) is int
int& j = i;        // decltype(j) is int&

If expr represents an expression that is not merely a name, then decltype(expr) is the type that evaluating expr would yield. I say would here because expr is not actually evaluated. Moreover, the result of decltype(expr) is a reference only if the expression yields an lvalue.

For example, after the definitions of i and j above, decltype(j+1) is int, decltype(i+1) is also int, and decltype((i)) is int&. It may be surprising that decltype(i) and decltype((i)) are two different types, but this difference comes about because i is a variable name and (i) is not.

One typically applies decltype to a variable as part of defining the type of a variable to be "just like that one over there." Such declarations are particularly useful when you combine them with auto. For example, after we have written

auto var = <i>expression</i>;

we may want to create another variable with the same type as var. We can do this by writing

auto var2 = var;

However, we might not want to initialize var2 at this point, perhaps because we are about to read into it:

cin >> var2;

We can define var2 to have the appropriate type without having to initialize it:

decltype(var) var2;

Programmers often apply decltype to expressions in order to write code that depends on those expressions' types. For example, the type of an ordinary integer literal is int if int is capable of containing the literal. Otherwise, it is long (and perhaps even long long). Therefore, decltype(1000000) is an easy way of writing "the narrowest integer type that is capable of containing the value 1000000."

As a more complicated example, consider a container c with an element type that we don't know. We would like to apply a function f to some of that container's elements and put f's results into a vector. How do we define that vector?

We can almost — but not quite — get away with writing

// <i>This definition fails if</i> f <i>returns a reference</i>
vector<decltype(f(c[0]))> v;

This definition has the right idea: It uses decltype to find out what type would result from applying f to an element of c. This application is always safe, even if c[0] does not exist, because the expression given to decltype is never actually evaluated; the compiler just figures out what type it would have if it were evaluated.

The trouble is that when we give an expression to decltype, decltype yields a reference type if the expression yields an lvalue. Without inspecting the definition of f, we don't know whether f returns an lvalue.

To make it easier to write programs such as this one, C++0x defines a library template named remove_reference (and several others with names such as add_reference, remove_const, and so on). We use this template this way:

// <i>This definition works even if</i> f <i>returns a reference</i>
vector<remove_reference<decltype(f(c[0]))>::type> v;

The general idea is that remove_reference is a template type that contains a type member named type. This member is the name of a type that matches remove_reference's template parameter, but with any top-level & removed. So, for example, remove_reference<int&>::type is a roundabout way of writing int.

This article just scratches the surface of the kinds of type manipulations that decltype makes possible. Fortunately, one does not need to understand them all in order to use decltype. The main point to remember is that decltype is really a single name for two related — but subtly different — concepts. One of them is determining the type of the declaration associated with a variable; the other is determining the type that would result from evaluating an expression. The rules for the two forms of decltype, especially when references are involved, are slightly different; it is important to understand those differences if you write programs that might depend on them.

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video