Decltype

Last updated

In the C++ programming language, decltype is a keyword used to query the type of an expression. Introduced in C++11, its primary intended use is in generic programming, where it is often difficult, or even impossible, to express types that depend on template parameters.

Contents

As generic programming techniques became increasingly popular throughout the 1990s, the need for a type-deduction mechanism was recognized. Many compiler vendors implemented their own versions of the operator, typically called typeof , and some portable implementations with limited functionality, based on existing language features were developed. In 2002, Bjarne Stroustrup proposed that a standardized version of the operator be added to the C++ language, and suggested the name "decltype", to reflect that the operator would yield the "declared type" of an expression.

decltype's semantics were designed to cater to both generic library writers and novice programmers. In general, the deduced type matches the type of the object or function exactly as declared in the source code. Like the sizeof [1] operator, decltype's operand is not evaluated.

Motivation

With the introduction of templates into the C++ programming language, and the advent of generic programming techniques pioneered by the Standard Template Library, the need for a mechanism for obtaining the type of an expression, commonly referred to as typeof , was recognized. In generic programming, it is often difficult or impossible to express types that depend on template parameters, [2] [3] in particular the return type of function template instantiations. [2]

Many vendors provide the typeof operator as a compiler extension. [4] As early as 1997, before C++ was fully standardized, Brian Parker proposed a portable solution based on the sizeof operator. [4] His work was expanded on by Bill Gibbons, who concluded that the technique had several limitations and was generally less powerful than an actual typeof mechanism. [4] In an October 2000 article of Dr. Dobb's Journal , Andrei Alexandrescu remarked that "having a typeof would make much template code easier to write and understand." [5] He also noted that "typeof and sizeof share the same backend, because sizeof has to compute the type anyway." [5] Andrew Koenig and Barbara E. Moo also recognized the usefulness of a built-in typeof facility, with the caveat that "using it often invites subtle programming errors, and there are some problems that it cannot solve." [6] They characterized the use of type conventions, like the typedefs provided by the Standard Template Library, as a more powerful and general technique. [6] However, Steve Dewhurst argued that such conventions are "costly to design and promulgate", and that it would be "much easier to ... simply extract the type of the expression." [7] In a 2011 article on C++0x, Koenig and Moo predicted that "decltype will be widely used to make everyday programs easier to write." [8]

In 2002, Bjarne Stroustrup suggested extending the C++ language with mechanisms for querying the type of an expression, and initializing objects without specifying the type. [2] Stroustrup observed that the reference-dropping semantics offered by the typeof operator provided by the GCC and EDG compilers could be problematic. [2] Conversely, an operator returning a reference type based on the lvalue-ness of the expression was deemed too confusing. The initial proposal to the C++ standards committee outlined a combination of the two variants; the operator would return a reference type only if the declared type of the expression included a reference. To emphasize that the deduced type would reflect the "declared type" of the expression, the operator was proposed to be named decltype. [2]

One of the cited main motivations for the decltype proposal was the ability to write perfect forwarding function templates. [9] It is sometimes desirable to write a generic forwarding function that returns the same type as the wrapped function, regardless of the type it is instantiated with. Without decltype, it is not generally possible to accomplish this. [9] An example, which also utilizes the trailing-return-type : [9]

int&foo(int&i);floatfoo(float&f);template<classT>autotransparent_forwarder(T&t)>decltype(foo(t)){returnfoo(t);}

decltype is essential here because it preserves the information about whether the wrapped function returns a reference type. [10]

Semantics

Similarly to the sizeof operator, the operand of decltype is unevaluated, so expressions like decltype(i++) will not result in an increment of the variable i. [11] Informally, the type returned by decltype(e) is deduced as follows: [2]

  1. If the expression e refers to a variable in local or namespace scope, a static member variable or a function parameter, then the result is that variable's or parameter's declared type
  2. Otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e; if e is an xvalue, the result is T&&; otherwise, e is a prvalue and the result is T.
  3. As a special case, decltype(auto) allows for type deduction like auto but it preserves the value category of the initializer. More specifically, it is equivalent to decltype(initializer).

These semantics were designed to fulfill the needs of generic library writers, while at the same time being intuitive for novice programmers, because the return type of decltype always matches the type of the object or function exactly as declared in the source code. [2] More formally, Rule 1 applies to unparenthesized id-expressions and class member access expressions. [12] [13] Example: [12] Note for added lines for bar(). Below the type deduced for "bar()" is plain int, not const int, because prvalues of non-class types always have cv-unqualified types, despite the statically declared different type.

constint&&foo();constintbar();inti;structA{doublex;};constA*a=newA();decltype(foo())x1;// type is const int&&decltype(bar())x2;// type is intdecltype(i)x3;// type is intdecltype(a->x)x4;// type is doubledecltype((a->x))x5;// type is const double&

The reason for the difference between the latter two invocations of decltype is that the parenthesized expression (a->x) is neither an id-expression nor a member access expression, and therefore does not denote a named object. [14] Because the expression is an lvalue, its deduced type is "reference to the type of the expression", or const double&. [11] The fact that extra parentheses introduce a reference qualifier to the type can be a source of errors for programmers who do not fully understand decltype. [15]

In December 2008, a concern was raised to the committee by Jaakko Järvi over the inability to use decltype to form a qualified-id, [1] which is inconsistent with the intent that decltype(e) should be treated "as if it were a typedef-name". [16] While commenting on the formal Committee Draft for C++0x, the Japanese ISO member body noted that "a scope operator(::) cannot be applied to decltype, but it should be. It would be useful in the case to obtain member type(nested-type) from an instance as follows: [17]

vector<int>v;decltype(v)::value_typei=0;// int i = 0;

This, and similar issues pertaining to the wording inhibiting the use of decltype in the declaration of a derived class and in a destructor call, were addressed by David Vandevoorde, and voted into the working paper in March 2010. [18] [19]

Availability

decltype is included in the C++ Language Standard since C++11. [12] It is provided by a number of compilers as an extension. Microsoft's Visual C++ 2010 and later compilers provide a decltype type specifier that closely mimics the semantics as described in the standards committee proposal. It can be used with both managed and native code. [10] The documentation states that it is "useful primarily to developers who write template libraries." [10] decltype was added to the mainline of the GCC C++ compiler in version 4.3, [20] released on March 5, 2008. [21] decltype is also present in Codegear's C++ Builder 2009, [22] the Intel C++ Compiler, [23] and Clang. [24]

Related Research Articles

<span class="mw-page-title-main">C++</span> General-purpose programming language

C++ is a high-level, general-purpose programming language created by Danish computer scientist Bjarne Stroustrup. First released in 1985 as an extension of the C programming language, it has since expanded significantly over time; as of 1997 C++ has object-oriented, generic, and functional features, in addition to facilities for low-level memory manipulation. It is almost always implemented as a compiled language, and many vendors provide C++ compilers, including the Free Software Foundation, LLVM, Microsoft, Intel, Embarcadero, Oracle, and IBM.

Generic programming is a style of computer programming in which algorithms are written in terms of data types to-be-specified-later that are then instantiated when needed for specific types provided as parameters. This approach, pioneered by the ML programming language in 1973, permits writing common functions or types that differ only in the set of types on which they operate when used, thus reducing duplicate code.

This is a list of operators in the C and C++ programming languages. All the operators listed exist in C++; the column "Included in C", states whether an operator is also present in C. Note that C does not support operator overloading.

Partial template specialization is a particular form of class template specialization. Usually used in reference to the C++ programming language, it allows the programmer to specialize only some arguments of a class template, as opposed to explicit full specialization, where all the template arguments are provided.

Barton–Nackman trick is a term coined by the C++ standardization committee to refer to an idiom introduced by John Barton and Lee Nackman as restricted template expansion.

The One Definition Rule (ODR) is an important rule of the C++ programming language that prescribes that classes/structs and non-inline functions cannot have more than one definition in the entire program and template and types cannot have more than one definition by translation unit. It is defined in the ISO C++ Standard 2003, at section 3.2. Some other programming languages have similar but differently defined rules towards the same objective.

C++ Technical Report 1 (TR1) is the common name for ISO/IEC TR 19768, C++ Library Extensions, which is a document that proposed additions to the C++ standard library for the C++03 language standard. The additions include regular expressions, smart pointers, hash tables, and random number generators. TR1 was not a standard itself, but rather a draft document. However, most of its proposals became part of the later official standard, C++11. Before C++11 was standardized, vendors used this document as a guide to create extensions. The report's goal was "to build more widespread existing practice for an expanded C++ standard library".

auto_ptr is an obsolete smart pointer class template that was available in previous versions of the C++ standard library, which provides some basic RAII features for C++ raw pointers. It has been replaced by the unique_ptr class.

sizeof is a unary operator in the programming languages C and C++. It generates the storage size of an expression or a data type, measured in the number of char-sized units. Consequently, the construct sizeof (char) is guaranteed to be 1. The actual number of bits of type char is specified by the preprocessor macro CHAR_BIT, defined in the standard include file limits.h. On most modern computing platforms this is eight bits. The result of sizeof has an unsigned integer type that is usually denoted by size_t.

The C and C++ programming languages are closely related but have many significant differences. C++ began as a fork of an early, pre-standardized C, and was designed to be mostly source-and-link compatible with C compilers of the time. Due to this, development tools for the two languages are often integrated into a single product, with the programmer able to specify C or C++ as their source language.

C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by the publication year of the specification, though it was formerly named C++0x because it was expected to be published before 2010.

In the C++ programming language, the assignment operator, =, is the operator used for assignment. Like most other operators in C++, it can be overloaded.

Substitution failure is not an error (SFINAE) is a principle in C++ where an invalid substitution of template parameters is not in itself an error. David Vandevoorde first introduced the acronym SFINAE to describe related programming techniques.

In computer programming, variadic templates are templates that take a variable number of arguments.

In C++ computer programming, allocators are a component of the C++ Standard Library. The standard library provides several data structures, such as list and set, commonly referred to as containers. A common trait among these containers is their ability to change size during the execution of the program. To achieve this, some form of dynamic memory allocation is usually required. Allocators handle all the requests for allocation and deallocation of memory for a given container. The C++ Standard Library provides general-purpose allocators that are used by default, however, custom allocators may also be supplied by the programmer.

Concepts are an extension to the templates feature provided by the C++ programming language. Concepts are named Boolean predicates on template parameters, evaluated at compile time. A concept may be associated with a template, in which case it serves as a constraint: it limits the set of arguments that are accepted as template parameters.

"typename" is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type. In the original C++ compilers before the first ISO standard was completed, the typename keyword was not part of the C++ language and Bjarne Stroustrup used the class keyword for template arguments instead. While typename is now the preferred keyword, older source code may still use the class keyword instead.

In computer programming, ellipsis notation is used to denote ranges, an unspecified number of arguments, or a parent directory. Most programming languages require the ellipsis to be written as a series of periods; a single (Unicode) ellipsis character cannot be used.

C++14 is a version of the ISO/IEC 14882 standard for the C++ programming language. It is intended to be a small extension over C++11, featuring mainly bug fixes and small improvements, and was replaced by C++17. Its approval was announced on August 18, 2014. C++14 was published as ISO/IEC 14882:2014 in December 2014.

In computer programming, a subroutine will often inform calling code about the result of its computation, by returning a value to that calling code. The data type of that value is called the function's return type.

References

  1. 1 2 Miller, William M. (2009-09-29). "C++ Standard Core Language Active Issues, Revision 66". ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-10-03.
  2. 1 2 3 4 5 6 7 Gregor, Douglas; Järvi, Jaakko; Siek, Jeremy; Stroustrup, Bjarne (2003-04-28). "Decltype and auto" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2015-08-28.
  3. Kalev, Danny (2008-05-08). "Clean Up Function Syntax Mess with decltype". DevX.com. Retrieved 2009-09-04.
  4. 1 2 3 Gibbons, Bill (2000-11-01). "A Portable "typeof" Operator". Dr. Dobb's Journal . Retrieved 2009-09-03.
  5. 1 2 Alexandrescu, Andrei (2000-10-01). "Generic<Programming>: Mappings between Types and Values". Dr. Dobb's Journal . Retrieved 2009-09-03.
  6. 1 2 Koenig, Andrew; Barbara E. Moo (2002-02-01). "C++ Made Easier: Naming Unknown Types". Dr. Dobb's Journal . Retrieved 2009-09-03.
  7. Dewhurst, Steve (2000-08-01). "Common Knowledge: A Bitwise typeof Operator, Part 1". Dr. Dobb's Journal . Retrieved 2009-09-03.
  8. Koenig, Andrew; Barbara E. Moo (2011-07-19). "4 Useful New Features in C++0x". Dr. Dobb's Journal . Retrieved 2012-01-12.
  9. 1 2 3 Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (2004-10-12). "Decltype and auto (revision 4)" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-09-04.
  10. 1 2 3 "decltype Operator". Microsoft Corporation . Retrieved 2009-09-04.
  11. 1 2 Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (2007-07-18). "Decltype (revision 7): proposed wording" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-09-04.
  12. 1 2 3 Becker, Pete. "Working Draft, Standard for Programming Language C++" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-09-04.
  13. Miller, William M. (2009-08-03). "C++ Standard Core Language Defect Reports, Revision 65". ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-09-15.
  14. Miller, William M. (2009-08-03). "C++ Standard Core Language Closed Issues, Revision 65". ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-09-04.
  15. Mazières, David (June 2021). "C++ value categories and decltype demystified" . Retrieved 2022-06-16.
  16. Dos Reis, Gabriel; Järvi, Jaakko; Stroustrup, Bjarne (2006-11-05). "Decltype (revision 6): proposed wording" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-10-03.
  17. Miller, William M. (2009-08-03). "C++ CD1 Comment Status". ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2009-10-03.
  18. Miller, William M. (2010-03-29). "C++ Standard Core Language Defect Reports, Revision 69". ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2010-04-10.
  19. Vandevoorde, Daveed (2010-02-03). "Core issues 743 and 950: Additional decltype(...) uses" (PDF). ISO/IEC JTC1/SC22/WG21 – The C++ Standards Committee. Retrieved 2010-04-10.
  20. "C++0x Support in GCC". Free Software Foundation. 2009-08-27. Retrieved 2009-09-04.
  21. "GCC 4.3 Release Series". Free Software Foundation. 2009-08-13. Retrieved 2009-09-04.
  22. "Type Specifier decltype (C++0x)". Embarcadero Technologies. Archived from the original on 2011-07-08. Retrieved 2009-09-04.
  23. "std, Qstd". Intel Corporation . Retrieved 2009-09-04.
  24. Gregor, Douglas (2011-01-26). "New C++0x feature support in Clang". Archived from the original on 2011-01-30.