C++ Insights is an open-source tool that transforms C++ source code into a representation closer to what compiler sees and generates. It helps understand the underlying details of C++.
1. Introduction Online version: https://cppinsights.io/
A binary release is available, allowing you to install the tool on your local machine. Upon opening it in the browser, a default example is displayed, demonstrating its capabilities. The left pane shows the input C++ source code, while the right pane presents the translated version enriched with additional information.
2. Translating range-based for loop before.cpp 1 2 3 4 5 6 7 int main () { std::vector<int > numbers = {1 , 2 , 3 , 4 , 5 }; for (int num : numbers) { std::cout << num << " " ; } return 0 ; }
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int main () { std::vector<int , std::allocator<int > > numbers = std::vector<int , std::allocator<int > >{std::initializer_list<int >{1 , 2 , 3 , 4 , 5 }, std::allocator <int >()}; { std::vector<int , std::allocator<int > > & __range1 = numbers; __gnu_cxx::__normal_iterator<int *, std::vector<int , std::allocator<int > > > __begin1 = __range1.begin (); __gnu_cxx::__normal_iterator<int *, std::vector<int , std::allocator<int > > > __end1 = __range1.end (); for (; __gnu_cxx::operator !=(__begin1, __end1); __begin1.operator ++()) { int num = __begin1.operator *(); std::operator <<(std::cout.operator <<(num), " " ); } } return 0 ; }
3. Translating template instantiation Let’s test a fold expression.
before.cpp 1 2 3 4 5 6 7 8 9 10 template <typename T, typename ... Ts>auto average (T value, Ts... values) { auto n = (1. + sizeof ...(Ts)); return ((value / n) + ... + (values / n)); } int main () { std::cout << average (1.0 , 2.0 , 3.0 ); return 0 ; }
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 template <typename T, typename ... Ts>auto average (T value, Ts... values) { double n = (1.0 + static_cast <double >(sizeof ...(Ts))); return ((value / n) + ... + (values / n)); } #ifdef INSIGHTS_USE_TEMPLATE template <>double average <double , double , double >(double value, double __values1, double __values2){ double n = (1.0 + static_cast <double >(2 )); return ((value / n) + (__values1 / n)) + (__values2 / n); } #endif int main () { std::cout.operator <<(average (1.0 , 2.0 , 3.0 )); return 0 ; }
4. Translating Lambda expression before.cpp 1 2 3 4 5 int main () { auto add = [](int a, int b) { return a + b; }; std::cout << add (3 , 4 ) << std::endl; return 0 ; }
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int main () { class __lambda_5_16 { public : inline int operator () (int a, int b) const { return a + b; } using retType_5_16 = int (*)(int , int ); inline constexpr operator retType_5_16 () const noexcept { return __invoke; }; private : static inline int __invoke(int a, int b) { return __lambda_5_16{}.operator ()(a, b); } }; __lambda_5_16 add = __lambda_5_16{}; std::cout.operator <<(add.operator ()(3 , 4 )).operator <<(std::endl); return 0 ; }
5. Translating implicit conversion In order to show implicit conversion, we need to enable Show all implicit casts
in the dropdown list.
before.cpp 1 2 3 4 5 6 7 8 void func (double i) {}int main () { func (3 ); unsigned int a = 1u ; char buff[3 ] = {1 , 2 }; return 0 ; }
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 void func (double i) {} int main () { func (static_cast <double >(3 )); unsigned int a = 1U ; char buff[3 ] = {static_cast <char >(1 ), static_cast <char >(2 ), '\0' }; return 0 ; }
5. Translating conversion operator before.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 struct A {};struct B { operator A () {return {};} }; void func (const A& a) {}int main () { B b; A a = b; func (B{}); return 0 ; }
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 struct A { }; struct B { inline operator A () { return {}; } }; void func (const A & a) {} int main () { B b; A a = b.operator A (); func (static_cast <const A>(B{}.operator A ())); return 0 ; }
6. Translating auto-type deduction before.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <initializer_list> auto a = 3 ;const auto ca = a;const auto & ra = a;auto && ref1 = a;auto && ref2 = ca;auto && ref3 = 3 ;auto a1 = 3 ;auto a2 (3 ) ;auto a3 = {1 };auto a4{3 }; int * p;const int * cp;const int * const ccp = cp;auto b1 = p;auto b2 = cp;auto b3 = ccp;
after.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <initializer_list> int a = 3 ;const int ca = a;const int & ra = static_cast <const int >(a);int & ref1 = a;const int & ref2 = ca;int && ref3 = 3 ;int a1 = 3 ;int a2 = 3 ;std::initializer_list<int > a3 = std::initializer_list<int >{1 }; int a4 = {3 };int * p;const int * cp;const int *const ccp = cp;int * b1 = p;const int * b2 = cp;const int * b3 = ccp;
When using auto
, the deduced type will:
Preserve top-level const for references.
Ignore top-level const for non-reference types.
Here, ccp
is not a reference, so the top-level const (the const on the pointer itself) is ignored, while the low-level const (the const on the object being pointed to) is preserved.