C++11 - The new standard Lars Kühne Institut für Informatik Lehrstuhl für theoretische Informatik II Friedrich-Schiller-Universität Jena January 16, 2013
Overview A little bit of history: C++ was initially developed by Bjarne Stroustrup in 1979 first ISO Standard in 1998 replaced by the corrigendum C++03 in 2003 (only bug fixes for the implementors) early draft in 2005: technical report 1 (TR1) next (and current) standard release in August, 2011: C++11 Surprisingly, C++11 feels like a new language - the pieces just fit together better. Bjarne Stroustrup
Things you won t miss std::auto ptr: got replaced by std::unique ptr the export keyword was supposed to allow separation of declaration and definition of templates no major compiler support still reserved dynamic exception specifications by default every function can throw anything exceptions specifications allow to restrict that not enforced at compile-time, hard to use correctly
Getting started recognize >> as closing a template declaration, instead of > > new keyword: noexcept void f o o ( ) n o e x c e p t ; a guarantee by the programmer to the compiler to guide optimizations compile-time assertions: static assert Example (static assert) template <typename T> void bar ( const T& x ) { s t a t i c a s s e r t ( s t d : : i s i n t e g r a l <T>:: v a l u e, T must be i n t e g r a l ) ; // do some a r i t h m e t i c... }
default, delete, final and override Example c l a s s A { p u b l i c : A( ) = d e f a u l t ; A( const A&) = d e l e t e ; v i r t u a l void f o o ( ) {} v i r t u a l void bar ( ) f i n a l {} } ; c l a s s B : p u b l i c A f i n a l { p u b l i c : v i r t u a l void f o o ( ) o v e r r i d e ; v i r t u a l void bar ( ) ; // e r r o r } ; c l a s s C : p u b l i c B ; // e r r o r
Extern templates Example in C++03 the compiler is required to instantiate every fully-specified template this may result in long compilation times, if the same template gets instantiated in different translation units // h e a d e r template <typename T> c l a s s Foo {/ compile time e x p e n s i v e d e f i n i t i o n / } ; // s o u r c e 1. o auto x = Foo<double >(); // s o u r c e 2. o > c o m p i l e s f o r a 2nd time! auto x = Foo<double >(); // s o u r c e 2 e x t e r n. o > no i n s t a n t i a t i o n o f Foo<double > extern template c l a s s Foo<double >; auto x = Foo<double >();
The problem with NULL Example as inherited by C, NULL is a Makro usually expanding to 0 void f o o ( i n t ) ; void f o o ( char ) ; // c a l l f o o (NULL ) ; new null-pointer constant: std::nullptr implicitely convertible and comparable to any pointer type not so for integral types, except for bool
The auto keyword old keyword with new meaning tells the compiler to deduce the type of the variable from its initialization i n t x = 4 ; // C++98 auto x = 4 ; // C++11 Serves as a convenience in cases where the type is either hard to write... s t d : : map<i n t, s t d : : v e c t o r <double> > my map ; // C++98 s t d : : map<i n t, s t d : : v e c t o r <double> >:: c o n s t i t e r a t o r i t = my map. b e g i n ( ) ; // C++11 auto i t = my map. c b e g i n ( ) ;
The auto keyword...or hard to know template <c l a s s A, c l a s s B> void f o o ( const A& a, const B& b ) { auto tmp = a b ; } // c a l l i n g the f u n c t i o n f o o ( u, v ) ; Inconvenient C++98 solution: template <c l a s s A, c l a s s B, c l a s s C> void f o o ( const A& a, const B& b ) { C tmp = a b ; } // c a l l i n g the f u n c t i o n foo<w>(u, v ) ;
The auto keyword strips off const-ness and references i n t a = 4 2 ; const i n t& b = a ; auto c = b ; // i n t // e x p l i c i t e l y add on q u a l i f i e r s const auto& d = c ; // c o n s t i n t& pointers, however, are treated as types of their own i n t a p t r = &a ; auto b p t r = a p t r ; // i n t auto c p t r = a p t r ; // i n t
The auto keyword and return-types return-types can be auto as well auto f o o ( ) > i n t { r e t u r n 4 ; } requires the programmer to provide a trailing-return-type template <c l a s s A, c l a s s B> auto f o o ( const A& a, const B& b ) > d e c l t y p e ( a b ) { r e t u r n a b ; } decltype is a new compile-time operator that returns the type of the given expression trailing-return-type especially useful with multiple return-statements (std::common type)
Range-based for-loop Example allows for a more compact way to express an iteration over a range an object is a range, if 1 its type either has the members begin() and end() returning valid iterators 2 or there are functions begin(obj) and end(obj) doing so all STL containers, regular-expression matches and initializer lists are iterable using range-based for loops s t d : : v e c t o r <i n t > v ; //... f i l l v... f o r ( i n t i : v ) s t d : : cout << i << s t d : : e n d l ; f o r ( auto& i : v ) // c o n s t a l s o p o s s i b l e i = i i ;
Lambda functions Example (What s wrong with this picture?) c l a s s SquareFunctor { p u b l i c : template <typename S c a l a r > S c a l a r operator ( ) ( const S c a l a r v a l u e ) { r e t u r n v a l u e v a l u e ; } } ; template <c l a s s I t e r a t o r > void s q u a r e ( I t e r a t o r begin, I t e r a t o r end ) { SquareFunctor mysquarefunctor ; s t d : : f o r e a c h ( begin, end, mysquarefunctor ) ; } a lot of code to square a number required a named entity for a one-liner
Lambda functions Example template <c l a s s I t e r a t o r > void s q u a r e ( I t e r a t o r begin, I t e r a t o r end ) s t d : : f o r e a c h ( begin, end, [ ] ( double v a l u e ) { r e t u r n v a l u e v a l u e ; } ) ; Definition (Lambda) 1 capture []: wildcard & and =, or named variables from scope 2 function body {} 3 no return type: is deduced by the compiler 4 optional: trailing return-type 5 under the hood: the compiler defines and intantiates a full-fledged function object
Lambda functions Example s t d : : map<i n t, s t d : : s t r i n g > mymap ; const i n t i d x = 3 ; // f i l l map... // the c o m p i l e r c a p t u r e s a l l the v a r i a b l e s // used i n the body by r e f e r e n c e auto lambda 1 = [&] ( ) { r e t u r n mymap [ i d x ]. s i z e ( ) > 0 } ; // copy the idx, but c a p t u r e the map by r e f e r e n c e auto lambda 2 = [=,&mymap ] ( ) { r e t u r n mymap [ i d x ]. s i z e ( ) > 0 } ; // c a l l the lambda i f ( lambda 1 ( ) ) e x i t ( EXIT SUCCESS ) ; convenient inline function-declaration C++11-lambdas are not polymorphic (yet)
Rvalue references Example motivation: avoid creating temporaries s t d : : v e c t o r <s t d : : s t r i n g > v ; v. push back ( C++11 ) ; 1 implicitely: calls std::string(const char*) this creates the temporary! 2 calls v.push back(const std::string&) this appends a copy of the temporary 3 implicitely: calls std::string:: string() on the temporary unnecessary constructor and destructor call
Rvalue references idea: reuse the temporary for the final result What makes a temporary/rvalue? Definition (Lvalues and Rvalues) inspired by the side of = they are usually found i n t n = 3 ; // n i s an l v a l u e 5 = n + 7 ; // 5 i s an r v a l u e ( compile time e r r o r ) lvalues (their address) still exists after the statement rvalues do not exist anymore after the statement (even though one might have kept the address)
Rvalue references are defined with && mutable rvalues (exclusively!) bind to rvalue-references special treatment for temporaries binding-rules & const & && const && lvalue x x x x const-lvalue x x rvalue x x x const-rvalue x x
Rvalue references Example (Overload resolution) void f o o ( s t d : : s t r i n g &); void f o o ( const s t d : : s t r i n g &); void f o o ( s t d : : s t r i n g &&); void f o o ( const s t d : : s t r i n g &&); f o o ( l v a l u e ) ; // v o i d f o o ( s t d : : s t r i n g &); f o o ( c o n s t l v a l u e ) ; // v o i d f o o ( c o n s t s t d : : s t r i n g &); f o o ( r v a l u e ) ; // v o i d f o o ( s t d : : s t r i n g &&); f o o ( c o n s t r v a l u e ) ; // v o i d f o o ( c o n s t s t d : : s t r i n g &&); Easy rules: rvalues prefer rvalue-references lvalues prefer lvalue-references must respect const-ness
Rvalue references 1 in practice: const & und && 2 copy-/move-constructors and assignment-operators 3 the compiler recognizes temporaries by resolving them to &&-overloads basis for move semantic Example (Move-semantic methods) c l a s s Foo { p u b l i c : Foo ( ) ; Foo ( const Foo &); Foo& operator=(const Foo &); // move c o n s t r. and assignment op. Foo ( Foo&&); Foo& operator=(foo&&); } ; Foo x ( Foo ( ) ) ; // c a l l s Foo ( Foo&&)
Rvalue references Example (Move Semantics) c l a s s AlsoMovable { } ; c l a s s Moveable { p u b l i c : Moveable ( s t d : : s i z e t s i z e ) : b i g A r r a y (new double [ s i z e ] ) {} } Moveable ( Moveable&& o t h e r ) : b i g A r r a y ( o t h e r. b i g A r r a y ), am ( s t d : : move ( o t h e r. am) ) { o t h e r. b i g A r r a y = s t d : : n u l l p t r ; } Moveable ( ) { d e l e t e b i g A r r a y ; } p r i v a t e double b i g A r r a y ; AlsoMovable am ;
Rvalue references rvalue-references are useful when there is more to move than just basic data types (int, float, pointers,...) big chunks of dynamically allocated memory (moveable) members of some other class type the STL is now move-enabled: container-classes provide move-insertion std::unique ptr is move-only not every moveable can be detected by the compiler Example (user-guided moving) template <c l a s s T> void swap (T& x, T& y ) { T tmp ( s t d : : move ( x ) ) ; x = s t d : : move ( y ) ; y = s t d : : move ( tmp ) ; } std::move turns lvalue-references into rvalue-references
Variadic Templates templates can now have an arbitrary number of arbitrary types Definition (Parameter Pack) indicated with the ellipsis operator:... 1 Template: holds variadic template parameters 2 Function: holds the corresponding function arguments Example template <c l a s s... Types> c l a s s t u p l e ; template <c l a s s T, c l a s s... Args> s t d : : s h a r e d p t r <T> make shared ( Args &&... a r g s ) ; template <c l a s s T, s t d : : s i z e t... Dims> c l a s s MultiDimArray ;
Variadic Templates - Unpacking:... Example template <c l a s s... Args> c l a s s CountArgs ; template <c l a s s T, c l a s s... Args> c l a s s CountArgs<T, Args... > { p u b l i c : const s t a t i c i n t v a l u e = CountArgs<Args... > : : v a l u e + 1 ; } ; // no arguments matches, t o o template <> c l a s s CountArgs<> { p u b l i c : const s t a t i c i n t v a l u e = 0 ; } ; CountArgs<i n t, f l o a t, double >:: v a l u e ; // 3 sizeof...(args) does the same
Variadic Templates - Unpacking patterns Example the...-operator unpacks every element according to the pattern to its left template <c l a s s T, c l a s s... Rest> // add c o n s t and & to each element o f Rest void p r i n t ( const T& obj, const Rest &... r e s t ) { s t d : : cout << o b j ; // don t add a n y t h i n g to r e s t p r i n t ( r e s t... ) ; } template <c l a s s F, c l a s s... Types> void c a l l (F foo, const Types &... t y p e s ) { // t r a n s l a t e s i n t o : f o o ( bar ( t y p e s 1 ), bar ( t y p e s 2 ),... ) f o o ( bar ( t y p e s )... ) ; }
Still more polymorphic function-wrappers type-traits for meta-programming comprehensive number-generation facilitiy regular expressions hash-based unordered containers user-defined literals, initializer lists,... The ISO plans on publishing the next revision C++1y until 2017. There is now an official community website: isocpp.org
Thank you! Questions? Overview of the new C++(C++11) - Scott Meyers C++11 - the final draft (N3337) - ISO cppreference.com, cplusplus.com