Type inference and deduction
1、C++中,deduction特指: template argument deduction;inference特指: auto
2、本章主要讨论type inference,type deduction放到了C++\Language-reference\Template
章节
wikipedia C++11 # Type inference
In C++03 (and C), to use a variable, its type must be specified explicitly. However, with the advent of template types and template metaprogramming techniques, the type of something, particularly the well-defined return value of a function, may not be easily expressed. Thus, storing intermediates in variables is difficult, possibly needing knowledge of the internals of a given metaprogramming library.
NOTE: 上面描述的难以描述type的问题,在wikipedia decltype中描述了这种情况的一个典型的案例:
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.[8] An example, which also utilizes the trailing-return-type:[8]#include <iostream> int g_IntValue = 1; int& foo(int& i) { std::cout << __PRETTY_FUNCTION__ << std::endl; return g_IntValue; } float foo(float& f) { std::cout << __PRETTY_FUNCTION__ << std::endl; return 0.0; } template<class T> auto transparent_forwarder(T& t) -> decltype(foo(t)) { return foo(t); } int main() { int i = 0; float j = 0.0; transparent_forwarder(i); transparent_forwarder(j); } // g++ --std=c++11 test.cpp
在
./decltype
章节中描述了更多的案例。解决思路是由compiler来进行type inference。
C++11 allows this to be mitigated(缓解) in two ways.
First approche: auto
First, the definition of a variable with an explicit initialization can use the auto
keyword.[11][12] This creates a variable of the specific type of the initializer:
auto some_strange_callable_type = std::bind(&some_function, _2, _1, some_object);
auto other_variable = 5;
The type of some_strange_callable_type
is simply whatever the particular template function override of std::bind
returns for those particular arguments. This type is easily determined procedurally(自动的) by the compiler as part of its semantic analysis duties, but is not easy for the user to determine upon inspection. The type of other_variable
is also well-defined, but it is easier for the user to determine. It is an int
, which is the same type as the integer literal.
This use of the keyword auto
in C++ re-purposes the semantics of this keyword, which was originally used in the typeless predecessor language B in a related role of denoting an untyped automatic variable definition.
auto
is also useful for reducing the verbosity of the code. For instance, instead of writing
for (std::vector<int>::const_iterator itr = myvec.cbegin(); itr != myvec.cend(); ++itr)
the programmer can use the shorter
for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr)
which can be further compacted since "myvec
" implements begin/end iterators:
for (auto& x : myvec)
This difference grows as the programmer begins to nest containers, though in such cases typedef
s are a good way to decrease the amount of code.
Second approche: decltype
Further, the keyword decltype
can be used to determine the type of expression at compile-time. For example:
int some_int;
decltype(some_int) other_integer_variable = 5;
This is more useful in conjunction with auto
, since the type of auto variable is known only to the compiler. However, decltype
can also be very useful for expressions in code that makes heavy use of operator overloading and specialized types.
NOTE: 最后一句话没有搞懂
The type denoted by decltype
can be different from the type deduced by auto
.
#include <vector>
int main()
{
const std::vector<int> v(1);
auto a = v[0]; // a has type int
decltype(v[0]) b = 1; // b has type const int&, the return type of
// std::vector<int>::operator[](size_type) const
auto c = 0; // c has type int
auto d = c; // d has type int
decltype(c) e; // e has type int, the type of the entity named by c
decltype((c)) f = c; // f has type int&, because (c) is an lvalue
decltype(0) g; // g has type int, because 0 is an rvalue
}
发展概述
C++11
1、auto
2、decltype
C++14
C++14 return type deduction for function 特性,参见:
1、C++14 # return type deduction for functions
C++14 decltype(auto)
对C++ 11 auto
+ decltype
+ trailing return type的简化,参见./decltype
。
C++17
C++17 新增 class template argument deduction 特性,参见:
1、cppreference C++17 # class template argument deduction
2、wikipedia C++17
C++17 新增 "Use of auto as the type for a non-type template parameter",参见
1、cppreference C++17 # non-type template parameters declared with auto
2、wikipedia C++17
为什么需要type inference?
从上面的**发展概述**来看,C++的一个非常重要的方向是对"type inference"的增强,那我们就需要思考: "为什么需要type inference"。
更好的支持generic programming
通过上面的描述可以看出,**type inference**是**generic programming**所必须的,在下面文章中对此进行了说明:
1) 在wikipedia decltype中对此有着很好的总结:
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]One of the cited main motivations for the
decltype
proposal was the ability to write perfect forwarding function templates.[8]
2) ./decltype
一个典型的需求就是: perfect forwarding function template。
Simplify C++/ Make C++ more expressive
减轻programmer的工作量,让programmer写更少的code。
TODO
https://www.geeksforgeeks.org/type-inference-in-c-auto-and-decltype/