? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Improve performance; Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Improve performance; Improve Standard Library; Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Improve performance; Improve Standard Library; Make C++ easier to teach and learn; Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Improve performance; Improve Standard Library; Make C++ easier to teach and learn; Keep (the not so easy) compatibility constraints; Christian S. Perone () C++0x 16 March 2011 4 / 65
? C++0x is a new standard for the next C++ generation. Intended to replace the current C++ standard (ISO/IEC 14882); Simplify simple tasks; Improve performance; Improve Standard Library; Make C++ easier to teach and learn; Keep (the not so easy) compatibility constraints; Fit into the real world; As of March 2011, ISO C++ Standards Committee has voted the C++0x specification to FDIS (Final Draft International Standard ) status, what makes it ready for review an approval by ISO. It can take 6 months to a year before the standard is officially published by ISO (expected to be released by the end of 2011). Christian S. Perone () C++0x 16 March 2011 4 / 65
advent of templates and template metaprogramming methods, some types became hard to use, some examples of this are: 1 std::vector<std::string>::const_iterator it1 = my_vec.cbegin(); 2 3 std::map<std::list<double>, // endless types ! continue next line... 4 std::set<std::vector<std::string> > >::iterator it2 = my_map.begin(); Consider now, the same example, this time using the auto-typed variables: 1 auto it1 = my_vec.cbegin(); 2 auto it2 = my_map.begin(); Note that since auto uses the return type to deduce the variable type, new iterators were added into the STL, like the vector::cbegin(), which returns a constant iterator. Christian S. Perone () C++0x 16 March 2011 6 / 65
1 auto my_variable; // error: a symbol whose type contains 2 // ’auto’ must have an initializer 3 4 auto my_variable1 = 20 + 21; // int 5 auto my_variable2 = 100 / 3; // int 6 auto my_variable3 = 100 / 3.0; // double 7 auto my_array = new int[50]; // int* 8 9 // sqrt has overload for 3 types, and we have passed a double as argument, 10 // this overload returns double, the type inference will be double. 11 auto my_variable4 = sqrt(my_variable3); Special example: 1 auto length = strlen("What is my platform ?"); Returns a 4-byte integer on a 32-bit compilation or 8-byte int on a 64-bit compilation. Christian S. Perone () C++0x 16 March 2011 7 / 65
decltype gives the type of the expression argument, without evaluating the expression, actually decltype only do a syntax check. Example: 1 std::string my_text = "lalalala"; 2 decltype(my_text) another_text; 3 4 decltype(my_text.length()) len_size; 5 // decltype doesn’t executes the string::length() method, it 6 // only uses the return type of the method to deduce the type Christian S. Perone () C++0x 16 March 2011 8 / 65
type is a new form to specify the return type of functions or templates. You’ll see that this form is specially useful for templates. Consider the follow examples: 1 auto get_value() -> float 2 { return 666.0; } In this new form, the auto keyword works just as a placeholder, the type specified in this form is now placed after the -> operator, which in our case is float. This form becomes more interesting when you use decltype to define the return type: 1 auto get_value() -> decltype(666.0) 2 { return 666.0; } Here the compiler will deduce (at compile time) what is the type of the constant 666.0 and use it as a return type of the function. Christian S. Perone () C++0x 16 March 2011 10 / 65
this template example: 1 template <typename FirstType, typename SecondType> 2 /*Unknown Type*/ AddThem(FirstType t1, SecondType t2) 3 { 4 return t1 + t2; 5 } The function adds two values and then returns the sum. But what if we pass an int and a double as arguments ? What should be the return type ? And if we pass two other distinct objects from distinct classes ? Christian S. Perone () C++0x 16 March 2011 11 / 65
here is why the trailing return type is useful: 1 template <typename FirstType, typename SecondType> 2 auto AddThem(FirstType t1, SecondType t2) -> decltype(t1 + t2) 3 { 4 return t1 + t2; 5 } The compiler will deduce at compile time what is the return type for the expression t1+t2 and then use it as the return type of our template. Please note that the expression t1+t2 isn’t evaluated, decltype only perform a syntax checking of the expression, it doesn’t executes the expression. Maps to... Note that the representation of the type definition operator -> is exactly the same used in Haskell, and it’s called ”maps to” (→) operator in mathematics; we’ll see it later again in the definition of Lambda functions. Christian S. Perone () C++0x 16 March 2011 12 / 65
currently support only two facilities to test assertions: assert macro; #error preprocessor directive; Citing the proposal (N1720 rev.3): To enforce a template parameter constraint, for example, it should be possible to write an assertion that will be tested when the associated template is instantiated. The assert macro tests assertions at runtime, which is far later than would be desired by the author of a template library, and which implies a runtime performance cost. The #error preprocessor directive is processed too early to be of much use in this regard. In particular, the #error directive is processed before templates are instantiated, and hence cannot be used to test assertions involving template arguments. Christian S. Perone () C++0x 16 March 2011 14 / 65
assert(constant-expression, string-literal); Examples: At namespace scope: 1 static_assert(sizeof(long) >= 8, "64-bit code generation not" 2 "enabled/supported."); At class scope: 1 template <class CharT, class Traits = std::char_traits<CharT> > 2 class basic_string { 3 static_assert(tr1::is_pod<CharT>::value, 4 "Template argument CharT must be a POD type in" 5 "class template basic_string"); 6 // (... ) 7 }; Christian S. Perone () C++0x 16 March 2011 15 / 65
very restrictive on the rules that define what is and what isn’t a constant expression. To ensure compile-time evaluation of constant expressions, developers are forced to use macros instead of inline functions. Example: 1 const int var_a = INT_MAX; 2 const int var_b = numeric_limits<int>::max(); 3 4 int array_a[var_a]; //fine 5 int array_b[var_b]; //error: "constant expression required" Only the var a using the constant INT MAX is evaluated at compile-time in the example above. The compiler often optimizes calls and use compile-time evaluation, but it isn’t obliged to do that. We need a way to ensure that a defined constant expression will always be evaluated at compile-time, otherwise we need to fall in an explicit error. Christian S. Perone () C++0x 16 March 2011 18 / 65
a constant expression is defined as: it returns a value (i.e., has non-void return type); its body consists of a single statement of the form return expr; it is declared with the keyword constexpr. Examples of valid constant expressions (citing the proposal): 1 constexpr int square(int x) 2 { return x * x; } // fine 3 4 constexpr long long_max() 5 { return 2147483647; } // fine 6 7 constexpr int abs(int x) 8 { return x < 0 ? -x : x; } // fine 9 10 constexpr void f(int x) // error: return type is void 11 { /* ... */ } Christian S. Perone () C++0x 16 March 2011 19 / 65
expressions (citing the proposal): 1 constexpr int next(int x) 2 { return ++x; } // error: use of increment 3 4 constexpr int g(int n) // error: body not just return expr 5 { 6 int r = n; 7 while (--n > 1) r *= n; 8 return r; 9 } 10 11 constexpr int twice(int x); 12 enum { bufsz = twice(256) }; // error: twice() isnt (yet) defined 13 14 constexpr int fac(int x) 15 { return x > 2 ? x * fac(x - 1) : 1; } 16 // error: fac() not defined before use Christian S. Perone () C++0x 16 March 2011 20 / 65
are templates which accept an arbitrary number of template arguments, providing for instance a clean implementation of type-safe printf() and class templates such as tuples. Christian S. Perone () C++0x 16 March 2011 22 / 65
variadic templates are used by the <tuple> library: 1 std::tuple<double, int> tup; 2 double value_0 = std::get<0>(tup); 3 std::get<1>(tup) = 666; Getting tuple information: 1 typedef std::tuple<int,double,int> MyTuple; 2 MyTuple tup(1, 2.0, 3); 3 4 int tup_size = std::tuple_size<MyTuple>::value; // 3 = Tuple size 5 std::tuple_element<0, MyTuple>::type value_0; // value_0 has the first el 6 value_0 = std::get<0>(tup); // value_0 has now the firs Christian S. Perone () C++0x 16 March 2011 25 / 65
a new strongly-typed enum with the follow properties: 1 Declared using enum class 1 enum class E {E1, E2, E3 = 100, E4 /* = 101 */ }; 2 Conversions 1 enum class E {E1, E2, E3 = 100, E4 /* = 101 */ }; 2 void f(E e) { 3 if( e >= 100 ) // error: no E to int conversion 4 // (...) 5 } 6 int i = E::E2; // error: no E to int conversion Christian S. Perone () C++0x 16 March 2011 28 / 65
is int) 1 enum class E : unsigned long {E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U}; 4 Scoping 1 enum class E {E1, E2, E3 = 100, E4 /* = 101 */ }; 2 E e1 = E1; // error 3 E e2 = E::E2; // ok Christian S. Perone () C++0x 16 March 2011 29 / 65
initializer lists is to allow the use of the brace-enclosed lists of expressions in all contexts that allow initializers. Example (before initializer lists): 1 std::vector<std::string> vec; 2 vec.push_back("How do I..."); 3 vec.push_back("...hate to use push_back..."); 4 vec.push_back("...every time I need an item"); Example (after initializer lists): 1 std::vector<std::string> vec = {"thank", "you", "god"}; 2 // or (equivalent) 3 std::vector<std::string> vec {"thank", "you", "god"}; Christian S. Perone () C++0x 16 March 2011 31 / 65
and the traditional initialization: 1 // C and C++ implicitly truncates: 2 3 int x = 2.5; // silent becomes x = 2 4 5 // In C++0x, the narrowing isn’t allowed: 6 7 double x = 2; // ok 8 int y {2.5}; // error, narrow type Christian S. Perone () C++0x 16 March 2011 33 / 65
to avoid the use of iterators in simple range loops, so we don’t need to care about iterators. The syntax of the new range-based for is: for(for-range-declaration : expression) statement Here is an example: 1 for(auto item : item_list) 2 std::cout << item; You could also use it to transform: 1 std::vector<int> item_list {1,2,3}; 2 for(auto &v : item_list) v++; 3 for(auto &v : item_list) 4 std::cout << v << std::endl; Will output: 2 3 4. Christian S. Perone () C++0x 16 March 2011 35 / 65
The current C++ standard (C++03) defines a special rule in which the 0 can be at same time an integer constant and a null pointer constant. This rule results in the follow confusion, consider those both overloaded functions: 1 void f(int); 2 void f(char *); The call to f(0) will resolve to f(int). There is no way to call f(char*) using a null pointer argument without using an explicit cast like f((char*)0). To solve this, they defined a new rule: 0 must be only an integer constant, and a new separate word was created to represent the null pointer: nullptr. Christian S. Perone () C++0x 16 March 2011 37 / 65
Examples1: 1 char* ch = nullptr; // ch has the null pointer value 2 char* ch2 = 0; // ch2 has the null pointer value 3 int n = nullptr; // error 4 int n2 = 0; // n2 is zero 5 6 if(ch == 0); // evaluates to true 7 if(ch == nullptr); // evaluates to true 8 if(ch); // evaluates to false 9 if(n2 == 0); // evaluates to true 10 if(n2 == nullptr); // error 11 if(nullptr); // error, no conversion to bool 12 if(nullptr == 0); // error 13 14 // arithmetic 15 nullptr = 0; // error, nullptr is not an lvalue 16 nullptr + 2; // error 1Examples cited as in the propostal. Christian S. Perone () C++0x 16 March 2011 38 / 65
empire The λ calculus was introduced in 1930 by Alonzo Church and is important for Computer Science because it provides simple semantics for computation with functions. One important observation from the λ calculus is that functions need not to be named, they can be written in anonymous form. Example (without types): 1 square_add(x, y) = x*x + y*y can be written as: (x, y) → x ∗ x + y ∗ y. Christian S. Perone () C++0x 16 March 2011 40 / 65
empire See for example, how λ takes its form in Python language: 1 map(lambda x: x*2, [1,2,3]) ... which can be read as: apply this lambda function ((x) → x ∗ 2) into the list [1, 2, 3]. Christian S. Perone () C++0x 16 March 2011 41 / 65
The same as λx → x ∗ 2.0: 2 auto lambda_function = 3 [](float x) { return x * 2.0; }; 4 5 float ret = lambda_function(2.0); // returns 4.0 Here we have declared a lambda function, assigned it into the lambda function variable, and then called it with the argument 2.0. Note that the compiler, in this case, was able to deduce the return type since it is a simple expression, but there are cases in which we need to do that explicitly. Christian S. Perone () C++0x 16 March 2011 43 / 65
look like simple functions, actually, they act like unnamed functions, but they’re represented by a closure type. When Lambda expressions are evaluated, they result in a closure object, containing the body of the Lambda expression as well the environment where the Lambda function is declared. The closure type of the Lambda expression has a public inline function call operator implemented, whose the parameters and return type are specified by the Lambda expression. Curiosity: ”The reason it is called a closure is that an expression containing free variables is called an open expression, and by associating to it the bindings of its free variables, you close it. - Ake Wikstrom (1987). Christian S. Perone () C++0x 16 March 2011 44 / 65
first example, we haven’t specified the trailing return type of the lambda: 1 // error: cannot deduce lambda return type from a braced-init-list 2 auto lambda_function = 3 [](int x){ return {1,2}; }; 4 5 // ok ! 6 auto lambda_function = 7 [](int x)->std::initializer_list<int> { return {1,2}; }; Since the return {1,2} (initializer list<int>) isn’t an expression, we need to specify the trailing return type explicitly. Christian S. Perone () C++0x 16 March 2011 45 / 65
used any variable of the upper-scope inside the lambda function, but you’ll need to do that in different flavors, and that’s why we have different Capture modes: Capture modes [] Capture nothing. [=] Capture everything by value. [&] Capture everything by reference. [var] Capture only var by value. [&var] Capture only var by reference. According to the propostal, for each entity captured by copy, an unnamed non-static data member is declared in the closure type. Christian S. Perone () C++0x 16 March 2011 46 / 65
nothing. 1 auto f1 = [](int x) { return x * 2; }; Example 2: Capturing everything by value. 1 int scope_value = 42; 2 auto f2 = 3 [=](int x) 4 { 5 scope_value++; // error here: scope_value is read-only 6 return x * scope_value; // ok 7 }; Christian S. Perone () C++0x 16 March 2011 47 / 65
everything by reference. 1 int scope_value = 42; 2 auto f3 = 3 [&](int x) 4 { 5 scope_value++; // ok 6 return x * scope_value; // ok 7 }; Christian S. Perone () C++0x 16 March 2011 48 / 65
variable by value. 1 int scope_value = 42; 2 int scope_value2 = 0; 3 4 auto f4 = 5 [scope_value](float x) 6 { 7 int ret = scope_value2; // error here: scope_value2 not captured 8 return x * scope_value; // ok 9 }; Christian S. Perone () C++0x 16 March 2011 49 / 65
variable by reference. 1 int scope_value = 42; 2 int scope_value2 = 0; 3 4 auto f5 = 5 [&scope_value](int x) 6 { 7 scope_value++; // ok 8 scope_value2++; // error: scope_value2 not captured 9 return scope_value * x; // ok 10 }; Christian S. Perone () C++0x 16 March 2011 50 / 65
capture mode. 1 int a = 1; 2 int b = 2; 3 int c = 3; 4 5 auto f6 = 6 [=, &c](int x) // capture everything by value, but "c" by reference. 7 { 8 c = 2; // ok 9 a = 1; // error: "a" is read-only 10 return scope_value * b; // ok 11 }; Christian S. Perone () C++0x 16 March 2011 51 / 65
of the arguments and before the specification of the trailing return type, we can specify the keyword mutable. This keyword makes the variables mutable. Example: 1 int a = 1; 2 auto f7 = 3 [=](int x) mutable // capture everything by value 4 { 5 a = 5; // ok 6 return x * a; // ok 7 }; Note that is ok to assign a value into the ”a” variable, but after calling this lambda function, you’ll note that the ”a” continues with value 1 instead of 5, this is because the variable inside the lambda scope is now a copy of the variable and not the variable itself or the reference. Christian S. Perone () C++0x 16 March 2011 52 / 65
the follow example: 1 int value = 0; 2 auto lambda_fun = [=] { return value; }; 3 value = 2; 4 std::cout << lambda_fun() << std::endl; What would be the value show ? The answer is 0. Remember the closures ! Christian S. Perone () C++0x 16 March 2011 53 / 65
? No more function pointers, now we have function objects (which are in fact the same type of a lambda function object): 1 void call_callback(int arg1, function<void(int)> callback_function) 2 { 3 callback_function(arg1); 4 } No more operator() overloading, many STL methods will be benefited Lambdas: 1 std::vector<int> vec {1,2,3,4}; 2 std::for_each(vec.begin(), vec.end(), [](int &v) { v*=v; }); Christian S. Perone () C++0x 16 March 2011 54 / 65
lvalue is an expression which identifies an object with extended life. It’s more intuitive to think in lvalues as the named “things” on the left side of expressions. rvalue is an expression which identifies an temporary object. This object goes away as soon as the expression ends, you can imagine rvalues as transient values. Christian S. Perone () C++0x 16 March 2011 56 / 65
// The reference1 is an lvalue reference 3 T& reference1 = a; 4 5 T b; 6 // The reference2 is an rvalue reference 7 T&& reference2 = b; 8 9 // The real difference 10 T& reference3 = T(); // Error, since T& isn’t const 11 T&& reference4 = T(); // Ok Ok, but why would I want this ? Christian S. Perone () C++0x 16 March 2011 57 / 65
the concept of Move Semantics. Copying is expansive, imagine for example two std::vectors, called v1 and v2; the follow statement: 1 std::vector<int> v1 = load_big_vector(); 2 std::vector<int> v2; 3 v2 = v1; The statement at line 3 will involve a function call, the memory pool allocation, and the copy of each item from v1 to v2. This is normal when we really need two copies of the same vector, but sometimes we don’t. Christian S. Perone () C++0x 16 March 2011 58 / 65
1 template <class T> 2 swap(T& a, T& b) 3 { 4 T tmp(a); // two copies of a 5 a = b; // two copies of b 6 b = tmp; // two copies of tmp 7 } In this case, we just want to swap variables and not make expansive copies here and there. Christian S. Perone () C++0x 16 March 2011 59 / 65
example using move semantics: 1 template <class T> 2 swap(T& a, T& b) 3 { 4 T tmp(std::move(a)); 5 a = std::move(b); 6 b = std::move(tmp); 7 } What std::move does is the conversion of the argument from a lvalue/rvalue to a rvalue, but it doesn’t guarantee the preservation of the argument data; you can imagine the std::move method as a potentially destructive read. Christian S. Perone () C++0x 16 March 2011 60 / 65
the std::move semantic: 1 std::vector<int> v = {1,2,3,4,5}; 2 std::vector<int> v2; 3 v2 = std::move(v); // Move, doesn’t copy ! 4 std::cout << v.size(); // Size: 0 Another example: 1 std::vector<int> return_vector() 2 { 3 std::vector<int> tmp {1,2,3,4,5}; 4 return tmp; 5 } 6 std::vector<int> vect = return_vector(); What std::move does is the conversion of the argument from a lvalue/rvalue to a rvalue, but it doesn’t guarantee the preservation of the argument data; you can imagine the std::move method as a potentially destructive read. Christian S. Perone () C++0x 16 March 2011 61 / 65
have support for some of the new C++0x features. GCC GCC started the implementation of the C++0x proposals since the version 4.3, the current development branch (4.6) is supporting more than 39 C++0x proposals, including but not limited to: Lambdas, range-based for, initializer lists, auto-typed variables, null pointer constant, constant expressions, static assertions,. . . In order to use GCC compiler with C++0x support, you must use the parameter -std=c++0x. Christian S. Perone () C++0x 16 March 2011 63 / 65
http://www2.research.att.com/ bs/C++0xFAQ.html Apache list of C++0x Compiler Support. http://wiki.apache.org/stdcxx/C++0xCompilerSupport Eq Solution: Weekly Snapshots of GCC dev. branch. http://www.equation.com/servlet/equation.cmd?call=fortran GCC C++0x Status page (with proposals used in this presentation). http://gcc.gnu.org/gcc-4.6/cxx0x status.html Explicating the new C++ standard. http://www.codeproject.com/KB/cpp/cpp10.aspx A Tutorial Introduction to the Lambda Calculus. http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf Christian S. Perone () C++0x 16 March 2011 65 / 65