This time is right Effective Modern C++ Study notes for Item 4.
From the previous introduction, we know that sometimes the results of type derivation are not very obvious. For the sake of safety, we'd better personally verify whether the type derivation meets our expectations. We can obtain some type derivation information in the following three stages:
- Code editing phase
- Compilation phase
- Operation phase
IDE Editors
Generally, when editing code, your IDE can often show some types of variables, functions, parameters and so on. For example, the following code shows that y1 is int type and y2 is const int * type when you point to y1 and y2 with the mouse.
#include <iostream> int main() { const int x = 2; auto y1 = x; auto y2 = &x; return 0; }
The reason why the IDE can know the result of type derivation is that the C + + compiler (at least the front end of the compiler) runs behind the IDE, which requires your code to be more or less compiled.
For simple types, the information displayed by IDE is usually useful, but for complex types, its derivation type may be inaccurate.
Compiler Diagnostics
A good way to get the error information is to deduce the compilation type:
#include <iostream> template<typename T> class TD; int main() { const int x = 2; auto y1 = x; auto y2 = &x; TD<decltype(y1)> y1Type; TD<decltype(y2)> y2Type; return 0; }
In the above code fragment, instantiating the template will lead to compilation errors. The error information is as follows:
main.cpp:11:22: error: aggregate 'TD<int> y1Type' has incomplete type and cannot be defined TD<decltype(y1)> y1Type; ^~~~~~ main.cpp:12:22: error: aggregate 'TD<const int*> y2Type' has incomplete type and cannot be defined TD<decltype(y2)> y2Type;
Type derivation information can be obtained from the above error message.
Runtime Output
The print type is more accurate and reliable when allowed. The first way is to control the output with typeid:
#include <iostream> int main() { const int x = 2; auto y1 = x; auto y2 = &x; std::cout << "y1: " << typeid(y1).name() << std::endl; std::cout << "y1: " << typeid(y2).name() << std::endl; return 0; }
Print information:
y1: i y1: PKi
i stands for int type, PKi code pointer to const int.
This looks good, but consider the following code:
template<typename T> // template function to be called void f(const T& param); std::vector<Widget> createVec(); // factory function const auto vw = createVec(); // init vw w/factory return if (!vw.empty()) { f(&vw[0]); // call f ... }
Use typeid to output the types of T and param. No matter which compiler, you will get wrong results. For example, Microsoft's compiler will tell you that both types are * class Widget const * *. However, param has one more const &. This is because the typeid here is passed by value. When deriving a type with template rules, Item1 knows that const and reference properties in const T & will be lost.
Fortunately, there is another method. Using the method provided by the Boost library, you can get reliable type derivation information:
#include <boost/type_index.hpp> template <typename T> void f(const T& param) { using std::cout; using boost::typeindex::type_id_with_cvr; cout << "T = " << type_id_with_cvr<T>().pretty_name() << '\n'; ` cout << "param = " << type_id_with_cvr<decltype(param)>().pretty_name(); << '\n'; ...` }
Template function boost::typeindex::type_id_with_cvr is instantiated using the type we passed, and it will not delete the existing const, volatile and reference semantics of the type (so the suffix is "with_cvr"). The return result of this template function is a boost::typeindex::type_index object, whose member function is pretty_name will generate a very friendly std::string to represent this type.
Running under the compiler of GUN and Clang, the result is:
T = Widget const* param = Widget const* const&
The results run under Microsoft compiler are consistent:
T = class Widget const * param = class Widget const * const &
summary
- You can usually use IDE editor, compiler error information and Boost TypeIndex library to view inferred types.
- The results of some tools may not be helpful or accurate, but they still have a thorough understanding of the type inference rules of C + +.