type
status
date
slug
summary
tags
category
icon
password
template type deduction
auto
type deduction introduced in C++11 is built on the template type deduction from C++ 98. For example: case 1 - ParamType is a reference or pointer, but not a universal Reference
in this situation, template type deduction works as below:
- if type of
expr
is a reference, then ignore the reference part when deducing the type ofT
- pattern-match type of
expr
againstPatamType
to determineT
type of
expr
→ remove reference → determine type of T
→ use T
to determine type of ParamType
case 2 - ParamType is a universal reference
in a function template taking a type parameter T, a universal reference’s declared type is
T&&
, which is like rvalue references- if
expr
is an lvalue, bothT
andParamType
are deduced to be lvalue references - this is the only situation in template type deduction where
T
is deduced to be a reference - although
ParamType
is declared using the syntax for an rvalue reference, its deduced type is an lvalue reference
- if
expr
is an rvalue, then case 1 rule applies
case 3 - ParamType is neither a pointer nor a reference
in this situation, we are dealing with pass by value, and that means param will be a copy of whatever is passed in - a completely new object
- if type of
expr
is a reference, ignore the reference type
- if
expr
isconst
orvalatile
, ignore these too - these type modifiers are ignored only for pass-by-value parameters, for parameters that are passed by reference, the const-ness of expr is preserved during type deduction
array arguments
Functions cannot declare parameters that are truly arrays. All array parameters passed by value are treated as a pointer declaration
however, functions are allow to declare parameters that are reference to arrays! Therefore, we have the following rule:
- if
ParamType
is a reference / pass-by-reference, then the type deduced forT
is the actual type of the array
- if
ParamType
is not a reference / pass-by-value, then the type deduced forT
is the pointer type
function arguments
function argument deduction is very similar to array argument deduction
- if passing by value, function types are deduced to function pointers
- if passing by reference, function types are deduced to function references
auto type deductions
when a variable is declared using
auto
, auto
plays the role of T
in the template type deduction, and the complete type specifier for the variable acts as ParamType
.The only case where auto type deduction and template type deduction leads to different results is that
auto
assumes that a braced initializer represents a std::initializer_list
, but template type deduction doesn’t.prefer auto to explicit type declarations
By using
auto
keyword, you always need to initialize your variable, because auto
variables have their type deduced from their initializer. Also, because auto
uses type deduction, it can represent types known only to compilers such as closure types:use explicitly typed initializer if necessary
The main strategy here is: use the explicitly typed initializer idiom when
auto
deduces undesired types. The explicitly typed initializer idiom involves declaring a variable with auto
, but casting the initialization expression to the type you want auto to deduce.decltype type deduction
Given a name or a expression, decltype tells you the name’s or the expression’s type. In C++11, the primary use for decltype is declaring function templates where the function’s return type depends on its parameter types:
Here, the use of
auto
before the function name has nothing to do with type deduction, it simply indicates that C++11’s trailing return type syntax is being used. Trailing return types can use the function’s parameters in the specification of the return type. In the above example, the return type is deduced using the parameter c
and i
. If we use the old fashion return type, c
and i
would be unavailable because they have not been declared yetIn C++ 14, we can omit the trailing return type, leaving just the leading
auto
, in this case, the template type deduction will take place. In the first example below, the function returns by value, so the reference part of the return value will be ignored based on template type deduction case 3. In the second example below, we are specifying that the return type should be deduced from the parameter types, but instead of using template type deduction, the decltype rules should be used:The use of
decltype(auto)
can be used anywhere that you want to apply the decltype
type deduction rules to the initializing expressionexceptions
Applying decltype to a name yields the declared type for that name - names are lvalue references, but that doesn’t affect
decltype
’s behavior.However, for lvalue expressions more complicated than names, decltype always deduce the type as an lvalue reference. If an lvalue expression other than a name has type
T
, decltype reports the type as T&
.view deduced type with boost library
The type information displayed by IDE editors and
std::type_info::name
are not reliable, but the type displayed by the Boost TypeIndex
library is usually reliable. Moreover, code using Boost libraries is nearly as portable as code relying on the standard library:with_cvr
in the function name means that this function takes a type argument and doesn't remove const, volatile, or reference qualifiersThis function produces a
boost::typeindex::type_index
object, whose pretty_name
member function produces a std::string
containing a human-friendly representation of the type.takeaway
template type deduction
- during template type deduction, arguments that are references are treated as non-references → their reference-ness is ignored
- when deducing types for universal reference parameters, lvalue arguments maintains their reference-ness
- when deducing types for pass-by-value parameters, const-ness and / or volatile-ness are ignored
- during template type deduction, arguments that are array or function names decay to pointers, unless they are used to initialize references
auto type deduction
auto
type deduction is usually the same as template type deduction, butauto
type deduction assumes that a braced initializer represents astd::initializer_list
, and template type deduction does not.
auto
in a function return type or a lambda parameter implies template type deduction, notauto
type deduction
decltype deduction
- decltype almost always yields the type of a variable or expression without any modifications
- for lvalue expressions of type
T
other than names, for example,(x)
, decltype always reports a type ofT&
- C++14 supports
decltype(auto)
, which deduces a type from its initializer, but it performs the type deduction using the decltype rules rather than theauto
or template type deduction rules
view deduced types
- deduced types can often be seen using IDE editors, compiler error messages, and the Boost
TypeIndex
library
- the type information displayed by IDE editors and
std::type_info::name
are not reliable, but the type displayed by the BoostTypeIndex
library is usually reliable - code using Boost libraries is nearly as portable as code relying on the standard library
- 作者:Zack Yang
- 链接:https://zackyang.blog/article/cpp-type-deduction
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章