// Listings: // Listing 1: Deduktionen mit auto //Source: int main() { const int x = 4; auto a = x; auto* pa = &x; auto& ra = x; auto ara = ra; } //C++ Insights: int main() { const int x = 4; int a = x; const int * pa = &x; const int & ra = x; int ara = ra; } // Listing 1 ende // Listing 2: Deduktionen mit decltype und decltype(auto) //Source: int main() { const int x = 4; decltype(x) d1 = x; decltype((x)) d2 = x; decltype(auto) d3 = x; decltype(auto) pd = &x; auto& ra = x; decltype(auto) dra1 = ra; decltype(ra) dra2 = ra; decltype((ra)) dra3 = ra; } //C++ Insights: int main() { const int x = 4; const int d1 = x; const int & d2 = x; const int d3 = x; const int * pd = &x; const int & ra = x; const int & dra1 = ra; const int & dra2 = ra; const int & dra3 = ra; } // Listing 2 ende // Listing 3: Ungenaue Floating-Point-Werte //Source: int main() { double dx = 3.14; for (double d=0.0; d<=1.0; d+=0.1) dx += d; } //C++ Insights: int main() { double dx = 3.1400000000000001; for(double d=0.0; d<=1.0; d+=0.10000000000000001) dx += d; } // Listing 3 ende // Listing 4: Typ-Aliase //Source: template class A{}; using AI = A; void f(AI); AI ai; //C++ Insights: template class A{}; // Template-Instanziierung entfernt using AI = A; void f(A); AI ai = A(); // Listing 4 ende // Listing 5: Zeichenketten-Konstanten mit auto“ als Strings deduzieren //Source: #include using namespace std; int main() { auto s = "C++"s; } //C++ Insights: #include using namespace std; int main() { std::basic_string< char, std::char_traits, std::allocator > s = std::operator""s("C++", 3UL); } // Listing 5 ende // Listing 6: Automatische Typ-Deduktion des Klassen-Template tuple //Source: #include using namespace std; int main() { tuple t{ 1, true, 2.25 }; } //C++ Insights: #include using namespace std; int main() { std::tuple t = std::tuple{1, true, 2,25}; } // Listing 6 ende // Listing 7: Automatische Typ-Deduktion des Containers vector //Source: #include using namespace std; int main() { vector v{ 1, 2, 3, 4 }; } //C++ Insights: #include using namespace std; int main() { std::vector > v = std::vector > {std::initializer_list{1, 2, 3, 4}, std::allocator()}; } // Listing 7 ende // Listing 8a: Implizite Typ-Konvertierungen I //Source: int main() { double d = 2.25; int x = d; long l = x; } //C++ Insights: int main() { double d = 2.25; int x = static_cast(d); long l = static_cast(x); } // Listing 8a ende // Listing 8b: Implizite Typ-Konvertierungen II //Source: int main() { short ss = 4; unsigned int ui = 6; auto res = ss + ui; } //C++ Insights: int main() { short ss = 4; unsigned int ui = 6; unsigned int res = static_cast(ss) + ui; } // Listing 8b ende // Listing 8c: Implizite Typ-Konvertierungen III //Source: void fct(double); void fct(long); int main() { fct(3.14f); } //C++ Insights: void fct(double); void fct(long); int main() { fct(static_cast(3.1400001F)); } // Listing 8c ende // Listing 9: Operator-Überladung //Source: #include using namespace std; int main() { cout << 42; } //C++ Insights: #include using namespace std; int main() { std::cout.operator<<(42); } // Listing 9 ende // Listing 10: Range-basierte for-Schleife //Source: #include #include using namespace std; int main() { vector v { 1, 2, 3, 4 }; for (auto x : v) { cout << x; } } //C++ Insights: #include #include using namespace std; int main() { std::vector > v = std::vector > {std::initializer_list{1, 2, 3, 4}, std::allocator()}; { std::vector > & __range1 = v; __gnu_cxx::__normal_iterator > > __begin1 = __range1.begin(); __gnu_cxx::__normal_iterator > > __end1 = __range1.end(); for(; __gnu_cxx::operator!=( __begin1, __end1); __begin1.operator++()) { int x = __begin1.operator*(); std::cout.operator<<(x); } } } // Listing 10 ende // Listing 11: Darstellen des Standard-Konstruktors als Kommentar //Source: class A { }; int main() { A a1; A a2(a1); a1 = a2; } //C++ Insights: class A { public: // inline constexpr A() noexcept = default; // inline constexpr A(const A &) noexcept = default; // inline constexpr A & operator=(const A &) noexcept = default; }; int main() { A a1 = A(); A a2 = A(a1); a1.operator=(a2); } // Listing 11 ende // Listing 12: Geerbte Konstruktoren in C++17 //Source: struct H { H(const H&) = delete; H(int); }; struct A { A(H); void f(H); }; struct B : A { B(); using A::A; void f(); using A::f; }; int main() { B b1; b1.f({0}); // Ok in C++11 & C++17 B b2({0}); // Error C++11, ok C++17 } //C++ Insights (C++17): struct H { // inline H(const H &) = delete; H(int); }; struct A { A(H); void f(H); // inline constexpr A(A &&) noexcept = default; }; struct B : public A { B(); void f(); using A::f; // void A::f(H); // inline constexpr B(B &&) noexcept = default; public: inline B(H) noexcept(false) : A() {} }; int main() { B b1 = B(); static_cast(b1).f(H{0}); B b2 = B(B{H(0)}); } // Listing 12 ende // Listing 13: Template-Instanziierung bei der Berechnung der Fakultät zur Compile-Zeit mit TMP //Source: template struct Faculty { static constexpr int value = V * Faculty::value; }; template<> struct Faculty<0> { static constexpr int value = 1; }; constexpr int v = Faculty<2>::value; //C++ Insights: template struct Faculty { static constexpr int value = V * Faculty::value; }; /* First instantiated from: insights.cpp:11 */ #ifdef INSIGHTS_USE_TEMPLATE template<> struct Faculty<2> { inline static constexpr const int value = 2 * Faculty<1>::value; }; #endif /* First instantiated from: insights.cpp:3 */ #ifdef INSIGHTS_USE_TEMPLATE template<> struct Faculty<1> { inline static constexpr const int value = 1 * Faculty<0>::value; }; #endif template<> struct Faculty<0> { inline static constexpr const int value = 1; }; constexpr const int v = Faculty<2>::value; // Listing 13 ende // Listing 14: Lambda-Ausdrücke entschlüsselt //Source: #include using namespace std; int main() { int x = 28; auto lbd = [x](){ return 2*x; }; cout << lbd(); } //C++ Insights: #include using namespace std; int main() { int x = 28; class __lambda_7_14 { public: inline /*constexpr */ int operator()() const { return 2 * x; } private: int x; public: __lambda_7_14(int _x) : x{_x} {} }; __lambda_7_14 lbd = __lambda_7_14{x}; std::cout.operator<<(lbd.operator()()); } // Listing 14 ende // Listing 15: Lambda ohne Capture-Ausdruck //Source: #include using namespace std; int main() { auto lbd = [](){ return 21; }; cout << lbd(); } //C++ Insights: #include using namespace std; int main() { class __lambda_6_14 { public: inline /*constexpr */ int operator()() const { return 21; } using retType_6_14 = int (*)(); inline /*constexpr */ operator retType_6_14 () const noexcept { return __invoke; }; private: static inline int __invoke() { return 21; } }; __lambda_6_14 lbd = __lambda_6_14{}; std::cout.operator<<(lbd.operator()()); } // Listing 15 ende // Listing 16: Generisches Lambda //Source: #include using namespace std; int main() { int x = 28; auto lbd = [x](auto arg){ return arg*x; }; cout << lbd(2); cout << lbd(2.5); } //C++ Insights: #include using namespace std; int main() { int x = 28; class __lambda_7_14 { public: template inline /*constexpr */ auto operator() (type_parameter_0_0 arg) const { return arg * x; } #ifdef INSIGHTS_USE_TEMPLATE template<> inline /*constexpr */ int operator()(int arg) const { return arg * x; } #endif #ifdef INSIGHTS_USE_TEMPLATE template<> inline /*constexpr */ double operator()(double arg) const { return arg * static_cast(x); } #endif private: int x; public: __lambda_7_14(int _x) : x{_x} {} }; __lambda_7_14 lbd = __lambda_7_14{x}; std::cout.operator<<(lbd.operator()(2)); std::cout.operator<<(lbd.operator()(2.5)); } // Listing 16 ende