Download presentation
Presentation is loading. Please wait.
Published byPhilip Hudson Modified over 7 years ago
1
NPRG051 Pokročilé programování v C++ Advanced C++ Programming
David Bednárek Jakub Yaghob Filip Zavoral
2
C++11/14/17/20 Syntax Types Libraries Later more info
auto, type inference & deduction, function return syntax, lambda, initialization, attributes Types char types, raw string, unicode & userdef literals Libraries chrono, filesystem, random, regex Later concurrency & parallelism generic programming & metaprogramming more info
3
auto
4
cyklus řízený rozsahem Kruliš 2014:
Range-based for C++03 C++11 cyklus řízený rozsahem Kruliš 2014: map<string,int> m; for (map<string,int>::const_iterator i = m.begin(); i != m.end(); ++i) i->second .. co je přehlednější? what is more readable? for (auto&& i : m) // a lot of space for my own valuable comments :-))) i.second .. EMC1-6 note: EMCxx referes to Scott Meyers: Effective Modern C++, Item xx
5
Generalized range-based for
supported data structures int x[], array, std:: containers user-defined containers to be implemented: begin(), end(), iterator with * != ++ different types of begin_expr / end_expr end_expr does not have to be an iterator be/ee must be comparable e.g. predicate as a range delimiter structured bindings ↪ for (auto&& i : m) // a lot of space for my own valuable comments :-))) i.second .. for( range_decl : range_expr) {..} auto && range = range_expr; auto begin = begin_expr ; auto end = end_expr ; for( ; begin!=end; ++begin) {..} C++17 predicate EMC1-6 note: EMCxx referes to Scott Meyers: Effective Modern C++, Item xx for( auto&& [first, second] : mymap)
6
!! e.g. proxy vector<bool>
Range-based for when not to use iteration other than begin⇝end access to more elements simultaneous iteration of multiple containers when to use common cases - 95% ? C++20: for( i:x) Idiom - use it! auto&& i : x applicable everywhere const auto& i : x read-only auto& i : x read/write auto i : x copy of each object! explicittype i : x cast really needed !! e.g. proxy vector<bool> temporal object vector<bool> -> temporal object - r-value - nenamatchuje se na auto& auto& : x - muze byt i vykonnostni problem, norma nezarucuje, ze var=*begin bude stejne vykonne jako pouziti primo *begin
7
Type inference - auto original C (1974) semantics problem C++11
local variable - storage class specifier redundant problem unnecessary verbosity, code explicit declaration is used for compiler checks only may enforce automatic conversions sometimes not intended C++11 inference of a variable type for the type of initializers strongly typed language ➟ compiler ! not a polymorphic type { auto int x; .. } std::vector<int> v = { .. }; std::vector<int>::const_iterator i = v.begin(); auto&& var = <initializer> --- I will accept any initializer regardless of whether it is an lvalue or rvalue expression and I will preserve its constness. If you then use std::forward on your auto&& reference to preserve the fact that it was originally either an lvalue or an rvalue, your code says: Now that I've got your object from either an lvalue or rvalue expression, I want to preserve whichever valueness it originally had so I can use it most efficiently - this might invalidate it. std::vector<int> v = { .. }; auto i = v.begin();
8
auto - be careful exact type C++03 C++11 What's the difference?
typedef vector<int> vecType; vecType v; vecType::const_iterator it = v.begin(); What's the difference? vector<int> v; auto it = v.begin();
9
auto - be careful exact type C++03 C++11 const_iterator
inferred type is silently changed cbegin(), cend() typedef vector<int> vecType; vecType v; vecType::const_iterator it = v.begin(); const_iterator iterator vector<int> v; auto it = v.begin(); const vector<int> v2; auto it2 = v2.begin(); const_iterator vector<int> v; auto it = v.cbegin();
10
auto - be careful! exact type C++03 C++11 any problem?
std::deque<int> v = { .. }; for( int i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } std::deque<int> v = { .. }; for( auto&& i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } any problem?
11
auto - be careful! exact type C++03 C++11 ... why?? where??
std::deque<int> v = { .. }; for( int i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } std::deque<int> v = { .. }; for( auto&& i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } ... why?? where??
12
auto - be careful! exact type use carefully when: size_t : unsigned
the interface depends on an exact type inference from a complex expression computation/correctness is based on an exact type size_t : unsigned std::deque<int> v = { .. }; for( int i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } int i: 1-2 = -1 std::deque<int> v = { .. }; for( auto&& i = v.size()-1; i>0; i-=2) { f( v[i], v[i-1]); } unsigned int i: 1-2 =
13
auto - be careful! exact type any problem?
for( auto&& i = 0; i < v.size(); ++i) .... any problem?
14
auto - be careful! exact type, size, ..., ... int i size_t
for( auto&& i = 0; i < v.size(); ++i) .... int i size_t 64-bit architectures: unsigned long long narrow type arithmetics
15
auto - why to use Correctness automatically guaranteed Maintenance
const_iterator ↫ const container& k.begin() Maintenance type changes (containers, templates, ...) Performance no implicit conversions Usability lambdas, binders, template parameters, template expressions Readability traditionally the motivation ... more use cases - templates, lambdas, later
16
Type inference Type deduction
17
Type inference in templates
without auto using auto vector< string> v; srt( v); tmp - what type? template <class T> void srt( T& x) { ?? tmp = x[0]; must be supported template<typename T> class vector { typedef T value_type; template <class T> void srt( T& x) { typename T::value_type tmp = x[0]; template <class V, class T> void srt( T& x) { V tmp = x[0]; user must specify vector< string> v; srt< string>( v); template <class T> void srt( T& x) { auto tmp = x[0]; no problem
18
Function parameters in templates
functions/methods in templates known container type unknown element type template <class T> class Srt { sort( T& x) { auto tmp = x[0]; if( lt( x[0], x[1])) ... } bool lt( ?? a, ?? b); what type of parameters? bool lt( auto a, auto b); error typedef auto V; bool lt( V a, V b);
19
Templates vs. auto relation between f and g
template <class T> void f( T x) { cout << x; } void g( auto x) { cout << x; }
20
Templates vs. auto template relation between f and g
f function template all functions with all applicable types of the parameter compiler deduces the type g syntax error compiler needs to deduce one particular type ⇝ Concepts TS / C++20 template <class T> void f( T x) { cout << x; } void g( auto x) { cout << x; } C++11/14 syntax error
21
Type inference in templates
external template template<typename V> bool lt(V& a,V& b) {} template <class T> class Srt { sort( T& x) { if( lt( x[0], x[1])) ... } is this correct?
22
Type inference in templates
external template nested template method template nested in class template accessibility and visibility rules similar to non-template classes ... even better? template<typename V> bool lt(V& a,V& b) {} template <class T> class Srt { sort( T& x) { if( lt( x[0], x[1])) ... } global function no access to members namespace pollution method template template <class T> class Srt { template<typename V> bool lt(V& a,V& b) {} sort( T& x) { if( lt( x[0], x[1])) ... } template <class T> class Srt { bool lt( ??(T[0])&a, ??(T[0])&b) {} idea: an expression of the required type
23
Type inference - decltype
type deduced from any expression not very useful for non-template programming very useful when used in templates and metaprogramming usage or better int i; decltype(i) j = 5; int f( decltype(i) x) { .. } expression not evaluated template <class T> class Srt { bool lt( decltype(*&T()[0])& a, decltype(*&T()[0])& b ) {} declval<T>()[0] can be used if no default constructor available T() a [] si ted muzu dovolit, protoze to od sortovatelneho kontejneru predpokladam. jinak lze i (T*)0 template <class T> class Srt { typedef decltype(*&T()[0]) V; bool lt( V& a, V& b ) {} compare compare typedef auto V; bool lt( V a, V b);
24
Type inference - comparison
external template nested template decltype decltype using typedef template<typename V> bool lt(V& a,V& b) {} template <class T> class Srt { sort( T& x) { if( lt( x[0], x[1])) ... } global function no access to members namespace pollution template <class T> class Srt { template<typename V> bool lt(V& a,V& b) {} sort( T& x) { if( lt( x[0], x[1])) ... } method template template <class T> class Srt { bool lt( decltype(*&T()[0])& a, decltype(*&T()[0])& b ) {} type inference expression not evaluated lze i decltype(declval<T>()) declval je hlavne pro metody trid bez konstruktoru template <class T> class Srt { typedef decltype(*&T()[0]) V; bool lt( V& a, V& b ) {} better readability
25
Return value syntax return type specification to the end of declaration inside class scope templates auto add( int x, int y) -> int; uhmm .. what's good for ?? class { enum Type { TA, TB }; Type getType(); }; Srt::Type Srt::getType() {} class Srt { enum Type { TA, TB }; Type getType(); }; auto Srt::getType() -> Type {} redundant scope duplication type inferred from parameters template <typename Builder> auto doit( const Builder& b) -> decltype( b.create()) { auto val = b.create(); return val; }
26
Return value syntax → int add templates - combinations of parameters
T = signed char U = unsigned char → int add template <class T, class U> ?? add( T t, U u); template <class T, class U> decltype((*(T*)0)+(*(U*)0)) add( T t, U u); what would you prefer? template <class T, class U> auto add( T t, U u) -> decltype(t+u); metaprogramming ⇝ later variadic templates, tuples, ...
27
Function return type deduction
automatic deduction of a return type from return expression C limited: only simple lambdas C extensive: all lambdas, all functions auto use template type deduction rule decltype(auto) - use decltype deduction rules ... wtf ... why ??? ⇝ type deduction rules! auto add( int x, int y); decltype(auto) add( int x, int y); different rules! auto f() { vector<int> v; return v[i]; } decltype(auto) f() { vector<int> v; return v[i]; } int int&
28
Type deduction C++98 C++11 - scope expands
used only for templates just works, detailed understanding rarely needed C scope expands auto variables, universal references, lambdas, decltype no more just works, different sets of rules! C scope expands further function return types, lambda init captures same rulesets, more usage contexts type deduction rules template - T, T&/T*, T&& auto objects decltype rulesetu je vic - lambdy etc. Meyers: Becker:
29
Template type deduction
function template PT is often different from T (e.g., const T&) implicit instantiation ET - type of expr deduction of PT and T from ET cases of PT: T&/T* - reference or pointer T&& - universal reference T - by-value template< typename T> void f( PT p); f( expr); // type: ET function template other types of templates must be instantiated explicitly only function templates may be instantiated implicitly class (etc) templates must be instantiated explicitly
30
Reference/pointer deduction
rules: if ET is a reference ⇒ discard reference match ET to PT and deduce T behavior of pointers as PT is similar template< typename T> void f( T& p); f( expr); // type: ET int x = 1; const int c = x; const int& r = x; f(x); // T&: int&, T: int f(c); // T&: const int&, T: const int f(r); // T&: const int&, T: const int ..... void f( T* p); const int* p = &x; f(&x); // T*: int*, T: int f(p); // T*: const int*, T: const int
31
Universal references rules: able to capture lvalue or rvalue
the same behavior as references, except: if expr is lvalue with type ET, T deduced as ET& template< typename T> void f( T&& p); f( expr); // type: ET able to capture lvalue or rvalue idea: - lvalue -> param is lvalue ref - rvalue -> param is rvalue ref !! int x = 1; const int c = x; const int& r = x; f(x); // lv - PT: int&, T: int& f(c); // lv - PT: const int&, T: const int& f(r); // lv - PT: const int&, T: const int& f(1); // rvalue - PT: int&&, T: int & && ⇒ & perfect forwarding reference collapsing ⇝ later rvalue - no special handling
32
T - both template and function parameter
By-value deduction rules: if type of expr is a reference ⇒ discard reference if expr is const or volatile ⇒ discard const/volatile T is (stripped) ET template< typename T> void f( T p); f( expr); // type: ET new object created int x = 1; const int c = x; const int& r = x; f(x); // T: int f(c); // T: int f(r); // T: int T - both template and function parameter
33
auto type deduction automatic objects auto behaves as T
except braced initializers ⇝ later auto never deduced to be a reference & or && have to be added int x = 1; const int c = x; const int& r = x; auto y1 = x; // int auto y2 = c; // int auto y3 = r; // int auto& y4 = x; // int& auto& y5 = c; // const int& (auto: const int) auto& y6 = r; // const int& const auto& y7 = x; // const int& (auto: int) const auto& y8 = c; // const int& (auto: const int) const auto& y9 = r; // const int& auto&& y10 = r; // ! const int& - lvalue const auto& ≈ PT auto ≈ T discard & lvalue ⇒ add & && & ⇒ &
34
decltype deduction rules:
decltype( name of type T) ⇒ T does not discard const/volatile/& decltype( lvalue_expr of type T) ⇒ T& auto always discards an outermost reference decltype either preserves it or even adds one ⇒ different rules for template / decltype deduction ↩ back to function return assignable int x = 1; const int& r = x; int a[1]; decltype(x); // int - name decltype((x)); // !! int& - lv decltype(r); // const int& decltype(a[0]); // int& - lv full rules are more complex, but this is sufficient for almost everyone
35
Function return type deduction
different rules auto use template type deduction rule decltype(auto) - use decltype deduction rules lvalue int expression auto ⇒ int decltype(auto) ⇒ int& Pozor!! name vs. lvalue expr auto f() { vector<int> v; return v[i]; } decltype(auto) f() { vector<int> v; return v[i]; } int int& vector<int> v; decltype(auto) f( size_t i) { return v[i]; } f(0) = 1; decltype(auto) g() { int x; return x; } decltype(auto) g() { int x; return (x); } name ⇝ int lvalue ⇝ int&
36
Lambda
37
Lambda - motivation find x < parameter... C++03 C++11 lambda
class ftor { public: ftor(int y) : y_(y) { } bool operator()(int x) const { return x<y_; } private: int y_; }; xxx::iterator i=find_if( v.begin(), v.end(), ftor( n)); auto i=find_if(v.begin(), v.end(), [=](int x){ return x<n; }); EMC31-32 (33, 34) lambda
38
[ captures ] ( params )opt mutableopt -> rettypeopt { statements; }
Lambda - syntax Syntax [ captures ] access to external local variables - initialization explicit/implicit, by-value/by-reference ( params ) call parameters optional but usual mutable local copy of external variable can be modified -> rettype return type, "new" syntax optional - compiler deduces type from expression template type deduction { statements; } lambda body [ captures ] ( params )opt mutableopt -> rettypeopt { statements; } what's the difference? [](){} []{}()
39
Lambda = funktor [ captures ] ( params ) -> rettype { statements; }
class ftor { private: CaptTypes captures_; public: ftor( CaptTypes captures ) : captures_( captures ) {} rettype operator() ( params ) { statements; } };
40
ambiguities not allowed
Lambda – capture capture defines which external variables are accessible and how local variables / this in the enclosing function determines the data members and constructor parameters of the functor explicit capture list of all enclosing local variables variables marked & passed by reference, the others by value value copy in time of definition! this - pointer to the enclosing object *this - copy of the enclosing - paralelism implicit capture external variables determined automatically by the compiler capture defines the mode of passing can be complemented by explicit capture generalized capture any expression move semantics [a,&b] [this,*this] C++17 [=] [=,&b] move v C jen pres funktor nebo binder [&] [&,a] C++14 [&,&a] [p=move(ptr)] ambiguities not allowed
41
Lambda - nested functions
an attempt to nest a function using lambda int f( int i) { int j = i*2; int g( int k) { return j+k; } j += 4; return g( 3); } "nested function" not possible in C++ int f( int i) { int j = i*2; auto g = [?]( int k) { return j+k; }; j += 4; return g( 3); } capture = (i*2)+3 & (i*2+4)+3 capture variables here
42
Lambda - capture default
What-if ... default capture by reference?? [] [&] ? function<void()> f() { int i = 0; auto fn = []{ DoWork( i); }; DoOtherWork( i); return fn; } what's wrong? function type: void function / lambda
43
Lambda - capture default
What-if ... default capture by reference?? [] [&] ? variable lifetime calling fn after return from f access to a nonexisting variable function<void()> f() { int i = 0; auto fn = []{ DoWork( i); }; DoOtherWork( i); return fn; } what's wrong?
44
Lambda - capture default
What-if ... default capture by value?? [] [=] ? vector<int> v = ReadBigVectorFromDisk(); auto first = find( v.begin(), v.end(), 42); auto lambda = []{ FindNext( v, first ); }; what's wrong?
45
Lambda - capture default
What-if ... default capture by value?? [] [=] ? efficiency deep copy of the vector correctness first not an iterator of v vector<int> v = ReadBigVectorFromDisk(); auto first = find( v.begin(), v.end(), 42); auto lambda = []{ FindNext( v, first ); }; what's wrong?
46
Lambda - no implicit default
good decision [] capture nothing! the programmer must specify the capture mode than maybe ... function<void()> f() { int i = 0; auto fn = [=]{ DoWork( i); }; DoOtherWork( i); return fn; } vector<int> v = ReadBigVectorFromDisk(); auto first = find( v.begin(), v.end(), 42); auto lambda = [&v,first]{ FindNext( v, first ); };
47
argument: user-defined statement(s)
Lambda as parameter common use case parameter in an algorithm how to write user-defined function? auto it = find_if( k.begin(), k.end(), [=](int x){ x < n; }); for_each( k.begin(), k.end(), [=](int& x){ ++x; }); vector<int> v; void each_even( lambada l) { auto i = v.begin(); while( i < v.end()) { l( *i); if( ++i < v.end()) ++i; } each_even( [](int& x){ ++x; }); parameter ? ? ? parameterized code execution argument: user-defined statement(s)
48
Lambda type C++11: type of lambda expression: std::function class
is a unique, unnamed nonunion class type the type cannot be named decltype cannot be used for variable declaration std::function class std::function<int(int,int)> sum subtle rt overhead - lambda as a member of std::function object auto - no overhead ?? sum = []( int x, int y) { return x+y; }; std::function<int(int,int)> sum = []( int x, int y) { return x+y; }; auto sum = []( int x, int y) { return x+y; };
49
usage must be applicable to the argument
Lambda as parameter auto not possible in parameters template compiler deduces a particular type vector<int> v; template <typename lambada> void each_even( lambada& l) { auto i = v.begin(); while( i < v.end()) { l( *i); if( ++i < v.end()) ++i; } each_even( [](int& x){ ++x; }); usage must be applicable to the argument
50
Lambda - type inference of parameters
C declaration of parametr types vector<int> v; vector<shared_ptr<T>> index; C++11 for_each( begin(v), end(v), []( decltype(*begin(v))& x) { cout<<x; } ); sort( begin(index), end(index), []( const shared_ptr<T> & p1, const shared_ptr<T> & p2) { return *p1<*p2; } auto get_size = []( unordered_multimap<wstring, list<string>> & m ) { return m.size(); }; template - unknown type complex type složitý typ
51
Lambda - type inference of parameters
C declaration of parametr types C auto vector<int> v; vector<shared_ptr<T>> index; C++11 C++14 for_each( begin(v), end(v), []( decltype(*begin(v))& x) { cout<<x; } ); sort( begin(index), end(index), []( const shared_ptr<T> & p1, const shared_ptr<T> & p2) { return *p1<*p2; } auto get_size = []( unordered_multimap<wstring, list<string>> & m ) { return m.size(); }; for_each( begin(v), end(v), []( auto& x ) { cout << x; } ); sort( begin(index), end(index), []( const auto& p1, const auto& p2) { return *p1<*p2; } auto get_size = [](auto& m ) { return m.size(); }; bonus: any container supporting size()
52
Lambda – ugly ducklings
where and why mutable? int a = 1, b = 1, c = 1; auto m1 = [a, &b, &c]() { auto m2 = [a, b, &c]() { cout << a << b << c; a = 4; b = 4; c = 4; }; a = 3; b = 3; c = 3; m2(); a = 2; b = 2; c = 2; m1(); where and how are variables captured std::function<int(int)> fact; fact = [&fact](int n)->int { if(n==0) return 1; else return (n * fact(n-1)); }; cout << "factorial(4) : " << fact(4); 123234 try to describe/draw the created data structures
53
Initializers
54
user-defined class template
initializer lists initialization of structures and containers template initializer_list initialization of user-defined classes ad-hoc variables or loops vector<string> v = { "xyz", "plgh", "abraca" }; vector<string> v ({ "xyz", "plgh", "abraca" }); vector<string> v { "xyz", "plgh", "abraca" }; class Person { long id; string name; int age; }; Person p = { , "My Name", 25 }; user-defined class template for( auto&& x : { 6, 7, 8}) .... auto y = { 9, 10, 11 }; for( auto&& i : y) .... template <class T> class S { vector<T> v; S( initializer_list<T> l) : v(l) {} void append( initializer_list<T> l) { v.insert( v.end(), l.begin(), l.end()); } }; S<int> s = { 1, 2, 3 }; s.append( { 4, 5}); EMC7 ad-hoc loop
55
Agregate initialization
initializace without a need to write a constructor differences in C++11/14/17 applicability: array, struct/class no private or protected non-static data members no virtual member functions C++11/14: no base classes C++17: no virtual, private, or protected base classes no user-provided constructors C++17: including those inherited from public bases explicitly defaulted or deleted constructors are allowed C++11/14: no default member initializers functionality copy-initialization in order of declaration array size deduction ∣initializes∣ < |members| ➟ default inicialization of the remaining members static data are ignored struct T { int x; string s; }; T t { 1, "ahoj"); An aggregate class or array may include non-aggregate public bases (since C++17), members, or elements, which are initialized as described above (e.g. copy-initialization from the corresponding initializer clause) Until C++11, narrowing conversions were permitted in aggregate initialization, but they are no longer allowed. Until C++11, aggregate initialization could not be used in a constructor initializer list due to syntax restrictions. Until C++14, the direct-initialization form T a {args..} did not permit brace elision.
56
Uniform initialization
uniform initialization - concept {} (braced) initializer - syntactic construction initialization syntax equivalent in many contexts ... but not everywhere! {} initializer ≈ implementation of uniform initialization use {} in all possible contexts ttt x( init); ttt y = init; ttt z{ init}; ttt z1 = { init};
57
Constructors and initializer_list
initial values of non-static data members uncopyable objects prohibits implicit narrowing conversions init expression is not expressible by the type of the initialized object immunity to most vexing parse anything that can be parsed as a declaration must be interpreted as one ➠ Prefer braced initialization syntax but ... class T { int x{ 0}; int y = 0; int z( 0); // error! }; () - explicit constructor UCO x{ 0}; UCO y( 0); UCO z = 0; // error! zeštíhlující ☺ double a, b, c; int x( a+b+c); int y = a+b+c; int z{ a+b+c}; // error! nejotravnější class T { public: explicit T( int t) {} T( const T& ) = delete; T& operator=( const T& ) = delete; }; int main() { T t( 0 ); T s { 0 }; T v = 0; // error } T x( 0); T y(); //fnc declaration T z{};
58
Constructors and initializer_list
{} initialization vs. initializer_list vs. constructor overloading {} init stricly prefers initializer_list if exists any way to use initializer_list, it will be used class T { T(int i, bool b); T(int i, float f); }; T x(10, true); // T(i,b) T y{10, true}; // T(i,b) T z(10, 5.0); // T(i,f) T u{10, 5.0}; // T(i,f) class T { T(int i, bool b); T(int i, float f); T(initializer_list<float> l); }; T x(10, true); // T(i,b) T y{10, true}; // T(l) T z(10, 5.0); // T(i,f) T u{10, 5.0}; // T(l) T( (float) 10, (float) true); class T { .... T(initializer_list<float> l); operator double() const; }; T v( x); // copy constructor T w{ x}; // T(l) !!! T ⇝ double ⇝ {double}
59
Constructors and initializer_list
{} initialization vs. initializer_list vs. constructor overloading {} init stricly prefers initializer_list class T { T(int i, bool b); T(int i, float f); T(initializer_list<bool> l); }; T u{10, 5.0}; // error !! narrowing conversion prohibited! class T { T(int i, bool b); T(int i, float f); T(initializer_list<string> l); }; T x(10, true); // T(i,b) T y{10, true}; // T(i,b) T z(10, 5.0); // T(i,f) T v{10, 5.0}; // T(i,f) OK - conversion does not exist
60
Empty initializer_list
no initialization parameters ⇒ default constructor empty list ⇒ initializer_list class T { T(); T(initializer_list<string> l); }; T x; // T() T y{} // T() T z(); // declaration! T u({}) // T(l) T v{{}} // T(l) {} means 'no arguments' most wexing parse {} means 'empty list'
61
Consequences and guidances
vector constructors vector( size_t size, T init_value) vector( initializer_list<T> l) guidances for class authors design your constructors so that the overload called isn’t affected by whether clients use () or {} initializers design additional overloads carefully initializer_list overshadows other overloads nonintuitive behavior in many contexts a new constructor overload can alter or even invalidate existing code ! guidances for class clients choose ()/{} initializers carefully good practice: choose one kind as a default use the other kind only if necessary no consensus that either approach is better than the other now considered as an error in the interface design vector<int> x( 10, 20); // v(i,T) vector<int> y{ 10, 20}; // v(l) !
62
Syntactic Constructions
63
worse readability for many users
Type alias std::unique_ptr<std::unordered_map<std::string, std::string>> 40 years old solution: typedef typedef up<um<s,s>> MapPtr; typedef void (*FP)(int, const string&); C++11: using using MapPtr = up<um<s,s>>; using FP = void (*)(int, const string&); main difference: templates / alias templates C++03: encapsulation to class/struct necessary worse readability for many users template<typename T> using MyAllocList = std::list<T, MyAlloc<T>>; MyAllocList<T> x; EMC9 template<typename T> struct MyAllocList { typedef std::list<T, MyAlloc<T>> type; }; MyAllocList<T>::type x;
64
dependent name ⇝ typename
Type alias usage in templates C++03: dependent name ⇒ typename C++11: template alias ⇒ must be a type std:: type transformations - type traits template<typename T> using MyAllocList = std::list<T, MyAlloc<T>>; template<typename T> class C { MyAllocList<T> x; // no typename, no ::type } template<typename T> struct MyAllocList { typedef std::list<T, MyAlloc<T>> type; }; template<typename T> class C { typename MyAllocList<T>::type x; } dependent name ⇝ typename C++11 C++14 remove_const<T>::type remove_const_t<T> const T → T remove_reference<T>::type remove_reference_t<T> T&/T&& → T add_lvalue_reference<T>::type add_lvalue_reference_t<T> T → T&
65
Delegating constructors
common functionality of constructor overloads C++03 C++11 class X { X( int x) { init( x); } X( string& s) { init( stoi(s)); } init( int x) { a = x<0 ? 0 : x; } int a; }; unnecessary verbose, not in an init-list - const, performance class X { X( int x) : a( x<0 ? 0 : x) {} X( string& s) : X( stoi(s)) {} int a; }; other constructor can be called directly jde to i zevnitr tela { X::X(a); }
66
Delegating constructors
complex computations in a constructor C++03 C++11 class Y { public: Y( int x) : a(f(x)+1), b(f(x)+2) {} private: int f( int x ) { return x*x; } int a, b; }; complex computation, side-effects, ... intermediate result computed first class Y { public: Y( int x) : Y( x, tmp( x)) {} private: struct tmp { int fx; tmp( int x) : fx( x*x) {}}; Y( int x, tmp t) : a(t.fx+1), b(t.fx+2) {} int a, b; };
67
Structured return values
functions returning more values C++03 void read( handle h, string& rs, bool& valid); read( db, s, valid); if( valid) doit( s); not a function-like syntax non-intuitive in/out par bool read( handle h, string& rs); if( read( db, s)) doit( s); non-intuitive separation unnecessary type verbose pair<string, bool> read( handle h); pair<string, bool> rs = read( db); if( rs.second) doit( rs.first); non-descriptive fields
68
Structured return values
pair<string, bool> read( handle h); auto rs = read( db); if( rs.second) doit( rs.first); more convenient ᴂᴂ read( handle h); ᴂᴂ(s,valid) = read( db); if( valid) doit( s); ? ? ? already defined variables
69
Structured return values
tuple, tie auto read( handle h) { return make_tuple(s,b); } tuple<string,bool> read( handle h) { return make_tuple(s,b); } tie(s,valid) = read( db); if( valid) doit( s); must be visible for type deduction unpacking tuple<string,bool> read( handle h); auto rs = read( db); f( rs); if( get<1>(rs)) doit( get<0>(rs)); result forwarding element access C++17 structured bindings decomposition declaration tuple f(....) { .... return {a,b,c}; } auto [x,y,z] = f(); auto [a,b,c] = { 1, 2, 3};
70
create initialized variable ഢ
Structured bindings C++17 structured binding declaration "decomposition declaration" like std::tie without having to have variables already defined uniquely-named variable referencable declared variables bound to initialized subobjects array, vector, ..., pair, tuple, struct auto [ identifier-list ] auto & [ identifier-list ] auto && [ identifier-list ] = expression ; { expression } ; ( expression ) ; int a[2] {1,2}; auto f() -> int(&)[2] { return a; } auto [x,y] = f(); auto& [xr, yr] = f(); create initialized variable ഢ x ≡ ഢ[0], y ≡ ഢ[1] rozdil mezi uniquely-named var a anonymous - muzu si na ni udelat ptr, ref, ... =ex - copy initialization {ex} (ex) - direct initialization xr ≡ a[0] yr ≡ a[1] if( auto [it,cc]=mmap.insert(val); cc) use(it); for( auto&& [first,second]:mymap)
71
Fold expressions variadic templates C++14 - recursion
C simplification auto old_sum(){ return 0; } template<typename T1, typename... T> auto old_sum(T1 s, T... ts){ return s + old_sum(ts...); } template<typename... T> ????( T... pack) ( pack op ... ) // P1 op (P2 op ... (Pn-1 op Pn)) ( ... op pack ) // ((P1 op P2) op ... Pn-1) op Pn ( pack op ... op init ) // P1 op (P2 op ... (Pn op init)) ( init op ... op pack ) // ((init op P1) op ... Pn-1) op Pn template<typename... T> auto fold_sum(T... s){ return (... + s); } template<typename... T> auto fold_sum1(T... s){ return ( s); } C++17 template<typename ...Args> void prt(Args&&... args) { (cout << ... << args) << '\n'; }
72
Static assertions C/C++03 - runtime checks C++11 - compile checks
expected state condition false ⇝ error message and abort programmers bugs protection debug mode only (#define NDEBUG) inactive in a release mode C compile checks compile-time checks, user-defined compiler error template parameters, data size, array range, constant values int f( char* p) { assert( p != 0); *p == ... if( false) message; abort; enum color { Blue, Red, Yellow, COLORS }; string color_names[] = { "Blue", "Red", "Yellow" }; static_assert( (sizeof(color_names) / sizeof(string)) == COLORS, "colors don't match"); concepts C ? still TS template<class Intgr> Integral f( Intgr x, Intgr y) { static_assert( is_integral<Intgr>::value, "parameter must be an integral type"); }
73
Attributes language extensions, compiler properties & hints
C/C++03: #pragma, __extkeyword C++11: attributes [[attr]] [[ns::attr(args)]] applicable in various contexts behavior defined by a platform unknown attributes ignored defined by compiler, plugins user-defined attributes not allowed (no C#) should not affect semantics common use optimization, statistics, parallelism support external interface (serialization, database, network, ...) int [[attr1]] i [[attr2, attr3]]; [[attr4(arg1, arg2)]] if (cond) { [[vendor::attr5]] return i; } narozdíl od C# nelze user-defined int x [[omp::shared]]; [[omp::parallel]] for(;;) [[likely(true)]] if(x==0) { .... } class [[db::object, db::table("people"))]] person { unsigned long id [[db::id, db::type("INT")]]; string first [[db::column("first_name")]]; string last [[db::column("last_name")]]; };
74
Standard attributes [[noreturn]] [[carries_dependency]] [[deprecated]]
function never returns _Exit, abort, exit, quick_exit, unexpected, terminate, rethrow_exception, throw_with_nested, nested_exception::rethrow_nested optimalization, warnings - dead code [[carries_dependency]] atomic, memory_order - later [[deprecated]] [[deprecated("reason")]] correct but deprecated use [[maybe_unused]] suppressed warnings [[noreturn]] void the_end() { ....whatever exit(); } obscure_type f() { if( smth_wrong) the_end(); else return obscure_type(); void g() { [[maybe_unused]] int y; assert(y==0); }
75
Standard attributes [[fallthrough]] [[nodiscard]]
switch (n) { case 1: case 2: f(); [[fallthrough]]; case 3: // no warning g(); case 5: // warning h(); break; } [[fallthrough]] switch fallthrough otherwise warning if break omitted [[nodiscard]] warning when return value is not used aplicable to type/function declaration syntax: [[ - always attribute beginning lambda! struct [[nodiscard]] mt {}; mt f(); [[nodiscard]] int g(); f(); // warning g(); // warning myArray[[]{ return 0; }()] = 1; syntax error
76
more C++17 template argument deduction for constructors
obsoletes many “make” helpers template<auto> non-type parameters map::insert_or_assign if/switch (init; condition) apply invoke the callable object with tuple as arg tuple, pair, array invoke constexpr lambdas hexadecimal float exponent: power of 2 Compiler support pair p(2, 4.5) // C++17 pair<int,double> p(2, 4.5) // C++11 auto p = make_pair(2, 4.5) // C++11 template <auto value> void f() {} f<10>(); // deduces int if(auto [it,cc] = mmap.insert(val); cc) use(it); float x = 0x1C.6p+3 (1*161+12*160+6*16-1)*23 int f( int x, int y) {..} auto a = make_tuple( 1, 2); std::apply( add, a); try_emplace(): if the key already exists, does not insert anything and does not modify the arguments. insert_or_assign(): inserts the mapped element or assigns it to the current element if the key already exists. insert_or_assign returns more information than operator[] and does not require default-constructibility of the mapped type. To achieve the same result with the current interface, one would need find, followed by a separate insertion if the key did not already exist. constexpr int f(int x) { return [x] { return x+10; } } auto f = [](int x) constexpr { return x; }
77
Types
78
optional a value may or may not be present bad_optional_access
useful for functions that may fail default conversion to bool bad_optional_access convenient value-or-whatever access pointer and reference operator * -> behavior undefined if value is not present more methods: emplace, swap, reset, make_optional operator<=> optional<string> f() { return Ӂ ? "Godzilla" : {}; } auto x = f(); if( x) // ≡ x.has_value() cout << x.value(); cout << x.value_or("empty"); optional<int> y{ 1}; cout << *y; *y = 2; optional<string> z{ "ahoj"}; z->size() ....
79
any container for values of any type any_cast - type-safe access
must be CopyConstructible any_cast - type-safe access bad_any_cast if not compatible pointer access possible confusing syntax test of type compatibility type_info& typeid( void) for empty value check of value presence more methods emplace, swap, make_any any x; x = "hello"; x = 1; if( x.has_value()) cout << any_cast<int>( x); if( x.type() == typeid( string)) .... x.reset(); int *p = any_cast<int>(&x); // !! vector<any> y{ 1, 2.9, "ahoj" }; cout << any_cast<int>(y[0]); cout << any_cast<double>(y[1]); cout << any_cast<string>(y[2]); string x.type().name() throw bad_any_cast vector<any> y{ .. string("ahoj") }; cout << any_cast<string>(y[2]);
80
variant type-safe union bad_variant_access index compile-time methods:
value of one of its alternative types references and arrays not allowed access by index or type bad_variant_access conditional pointer access index 0-based index of current alternative compile-time methods: variant_size, variant_alternative more methods: emplace, swap, operator <=> variant<int, float, string> v, w; v = 12; auto x = get<int>(v); v = "abcd"; auto y = get<2>(v); w = get<string>(v); w = x; cout << v.index(); // 2 if( holds_alternative<string>(v)) .... if( auto pv = get_if<int>(&v)) cout << *pv; else cout << "not an integer"; variant_alternative: index -> type int* null on error stay tuned! polymorphic visitor
81
variant polymorphic visitor C++17 C++20 ? parameter: any Callable
overloaded function, functor, lambda each type (value) is dynamically dispatched to the matching overload runtime! C++17 std::variant C++20 ? language variant - later polymorphic code or overloads using myvar = variant<int, double, string>; vector< myvar> vec{ 1, 2.1, "tri" }; for (auto&& v : vec) { visit([](auto&& arg) { cout << arg; }, v); myvar w = visit([](auto&& arg) -> myvar { return arg + arg; }, v); } must accept all variants variant alternative: index -> type return another variant common idiom
82
char types & unicode literals
fixed platform-independent width Unicode support u8"" - always UTF8 (e.g., ECBDIC) "žhář" ≠ u8"žhář" (default codepage, 5 vs. 8 bytes) UCS-2 older, fixed 2-byte UTF16 newer, superset, possibly 4-byte UTF32 ≅ UCS-4 C++03 char string "abc" implementationdefined wchar_t wstring L"abc" C++11 u8"abc\xFF\xFFFF" UTF8 char16_t u16string u"abc\uFFFF" UTF16/UCS-2 char32_t u32string U"abc\UF0F0F0F0" UTF32/UCS-4
83
raw string raw string literal who never made such a bug ?? \\ \\\\
escape chars does not apply all chars valid (newline, tab, ", ...) user-defined delimiter applicable to uR"", u8R"", ... f = open( "C:\temp\new.txt"); \\ \\\\ ('(?:[^\\']|\\.)*'|"(?:[^\\"]|\\.)*")| R" dch* ( ch* ) dch* " R"(('(?:[^\\']|\\.)*'|"(?:[^\\"]|\\.)*")|)" "(\'(?:[^\\\\\']|\\\\.)*\'|\"(?:[^\\\\\"]|\\\\.)*\")|" R""(A \b C)"" "\0" R"raw(GHI)raw"; "A\t\\b\nC\0GHI"; strings using different syntax concatenated
84
string_view string_view non-owning (sub-)string ref pointer + size
easy to create/pass bool cs( const string& s1, const string& s2); bool cv( string_view s1, string_view s2); string str = "my string"; cs( str, "string test"); cv( str, "string_view test");
85
User-defined literals
user-defined suffix integral number, floating-point number, character, string originally: STL extensibility useful, e.g., for computations using different units (CNN) Ztráta satelitu v hodnotě $ byla způsobena zmatkem v jednotkách užívaných mezi týmy řídícími let. Kilograms w = 200.5_lb _kg; Time t = 2_h + 23_m + 17_s; Year y = "MCMLXVIII"_r + 48; SomeType operator "" _suffix( const char *); SomeType operator "" _suffix( unsigned long long); SomeType operator "" _suffix( long double);
86
User-defined literals
Kilograms w = 200.5_lb _kg; Kilograms x = 200.5; // error only specialized constructor kg = not allowed class Kilograms { double rawWeight; public: class DoubleIsKilos{}; // a tag explicit constexpr Kilograms(DoubleIsKilos, double wgt) : rawWeight(wgt) {} }; constexpr Kilograms operator "" _kg( long double wgt) { return Kilograms{Kilograms::DoubleIsKilos{}, static_cast<double>(wgt)}; } constexpr Kilograms operator "" _lb( long double wgt) { return Kilograms{Kilograms::DoubleIsKilos{}, static_cast<double>(wgt*0.4535)}; conversion
87
Libraries
88
random C: stdlib rand generators distributors
generate uniformly distributed values linear_congruential, mersenne_twister, substract_with_carry, ... distributors transform a generated sequence to a particular distribution uniform, normal, poisson, student, exponential, ... usage: distributor( generator) 10 generators 20 distributors #include <random> default_random_engine generator; default_random_engine generator(time(0)); uniform_int_distribution<int> distrib(1,6); int dice_roll = distrib(generator); equal sequence seed generates 1..6 generator is called by distributor auto dice = bind( distrib, mt19937_64); auto dice = [](){ return distrib(mt19937_64); }; int wisdom = dice()+dice()+dice(); functor binding generator and distributor
89
chrono epoch duration clock
various time units time arithmetics strong type checking clock system_clock system real-time clock to_time_t(), from_time_t() - conversion from/to time_t steady_clock monotonic clock, never decreasing not realetd to wall clock time, suitable for measuring high_resolution_clock the clock with the shortest tick period available timepoint - time interval from the start of the clock's epoch
90
chrono various time units strong type checking
#include <iostream> #include <chrono> #include <thread> using namespace chrono; void sleep_ms( unsigned int ms) { auto t0 = high_resolution_clock::now(); this_thread::sleep_for( milliseconds(ms)); auto t1 = high_resolution_clock::now(); milliseconds total_ms = duration_cast<milliseconds>(t1 - t0); cout << total_ms.count(); } various time units strong type checking chrono::seconds twentySeconds(20); chrono::hours aDay(24); chrono::milliseconds ms; ms += twentySeconds + aDay; --ms; ms *= 2;
91
directories recursively
filesystem C++17 platform independent operations on file systems and their components paths, regular files, directories, symlinks/hardlinks, attributes, rights, ... ... finally - C++14 TS, C++17 std:: iterable filesystem possibly recursively copying, deleting, renaming, ... iterable paths and filenames parts of a path normalized concatenation dir( const string& tree) { fs::path treep( tree); for( auto&& de : fs::recursive_directory_iterator( treep)) { if( is_directory( de.status())) cout << ">> "; fs::path p( de ); cout << p.root_path() << ":" << p.parent_path() << ":" << p.filename() << ":" << p.stem() << ":" << p.extension() << endl; for(auto&& pi : p) cout << *pi; } directories recursively path parts
92
mnoho dalších přetížení
regex templates regex regular expression, various syntax match_results container for regex_search results cmatch = match_results<const char*> wcmatch smatch = match_results<string::const_iterator> wsmatch functions matching bool regex_match( string, regex) determines if regexp matches the entire string searching bool regex_search( string, smatch, regex) matches regexp to any part of string replacing string regex_replace( string src, regex, string fmt) searches for all appearances of regex in src; replaces them using fmt supported syntax ECMAScript, basic, extended, awk, grep, egrep many overloads mnoho dalších přetížení
93
Saturtag and Suntag, some Fritags.
regex #include <regex> const regex patt( R""((\+|-)?[[:digit:]]+)""); string inp = "-1234"; if( regex_match( inp, patt)) .... raw string - escape const regex patt( R"(\w+day)" ); string days = "Saturday and Sunday, some Fridays."; smatch match; if( regex_search( days, match, patt ) ) { cout << match[0]; } cout << regex_replace( days, regex( "day" ), "tag" ); Saturday \+ protoze + je ridici znak Saturtag and Suntag, some Fritags.
94
Upcoming Features & near future
95
Concepts expected: C++11 C++14 C++17 C++20?
currently still TS, but wording stable boolean predicates on template parameters evaluated at compile time limits the set of arguments that are accepted as template parameters no runtime overhead, negligible compilation overhead main uses simplified compiler diagnostics for failed template instantiations selecting function template overloads and class template specializations based on type properties argument satisfies more concepts ⇝ the most constrained concept is chosen constraining automatic type deduction Overload 129, /10, 2016/2 auto x = ....; Sortable x = ....; auto concept Convertible <typename T, typename U> { operator U(const T&); } template<typename U, typename T> requires Convertible<T, U> U convert(const T& t) { return t;
96
Standard Concepts foundational concepts functions iterators and ranges
Movable<T> Copyable<T> Equality_comparable<T>, Equality_comparable<T, U> Totally_ordered<T>, Totally_ordered<T, U>, Ordered<T> Semiregular<T>, Regular<T> functions Function<F, Args...>, Predicate<P, Args...>, Relation<P, T> Unary_operation<F, T>, Binary_operation<F, T> iterators and ranges Input_iterator<I>, Output_iterator<I, T> Forward_iterator<I>, Bidirectional_iterator<I, T> Random_access_iterator<I, T> Range<R>
97
Future not included in C++17 maybe C++20?
pilot implementation, practical experience, refined wording ranges (TS) (it, it), (it,cnt), (it,pred) based on concepts modules (TS) replacement of textual #include overloading operator . smart pointers ➟ smart references unified call syntax f(x,y) ≈ x.f(y) ≈ .f(x,y) ≈ .x.f(y) networking 2D graphics coroutines & parallelism reflection ... export { double g(double, int); int foo; namespace Calc { int add(int a, int b); } void not_exp_func(char* foo); import my_module;
98
Far future C++20 C++23? designated initializers contracts
preconditions, postconditions, assertions pattern matching and language variants generalized switch C++23? metaclass Point p{ .x = 3, .y = 4 }; distance({.x{}, .y{5}}, p); return inspect(exp) { sum {*(lit 0), *rhs} => simplify(rhs) sum {*lhs , *(lit 0)} => simplify(lhs) sum {*lhs , *rhs} => sum{....} _ => exp };
99
... stay tuned: concurrency & parallelism metaprogramming
100
Not Used ... ale můžou se hodit
101
ColorBlue FeelingBlue
enum class C++03 enum "unscoped enum" weakly typed value identifiers globally unique variable size decided by a compiler size/performance optimizations C++11 enum class "scoped enum" strongly typed local identifiers exactly defined variable size default: int ColorBlue FeelingBlue enum Color { Red, Blue, Green } x; enum Feelings { Happy, Sad } y; int Blue; if( x < y || y < 1) ... enum Color { Red, Blue, Green }; enum Feelings { Happy, Blue }; enum class E1 { Red, Blue } x; if( x == 1) ... int a = static_cast<int>(x); enum class E2 : uint8_t { Happy, Blue }; E2 y { E2::Blue }; auto z = E2::Happy; y = blue; y = E1::blue; EMC10 scoped enum
102
C++11 scoped & unscoped enum
declaration of an underlying type forward declaration elimination of the entire project recompilation usefulness of unscoped enum implicit conversion to an integral type bitmask, tuple, ... redundant verbosity enum in a class enum E3 : unsigned short { Xxx, Yyy }; enum class E4 : uint32_t { Xxx, Yyy }; values needed for implementation enum E5 : int; enum class E6; void f( E6 e); u.t. enum class E6 { Arsenal, Liverpool }; void f( E6 e) { if( e == E6::Arsenal) .... header - declaration auto x = get<static_cast <size_t>(Ids::idName)>(r); enum Ids { idName, idAddress, idYear }; using Row = tuple<string, string, int>; Row r; auto x = get<idName>(r);
103
default, delete C++03 object copying prevention - private constr, op= automatically generated methods X::X(), X::X( const& X), X::operator=( const& X), X::~X() default constructor is not generated if an explicit constructor defined C++11 better control delete: compiler error instead of linker error default: generated constructor explicitly added class X { X() = default; X( int i) { .... } X( const& X) = delete; X& operator=( const& X) = delete; }; EMC11
104
override, final C++11 C++03 override
context keyword can be in identifier in other context C++03 undesired overloading overloading ╳ overriding přetížení ╳ .... "přeplácnutí" non-intuitive use of virtual in a derived class C++11 override base class virtual method must be defined final Переопределение Bednárek 2017 class Base { virtual void f( double); }; class Derived : Base { virtual void f( int) override; class Base { virtual void f( double); }; class Derived : Base { virtual void f( int); Base* b = new Derived; f(0); syntax error syntax error EMC12 final - prevence VMT, optimalizace class FBase final {}; class FDerived : FBase {}; use carefully! prevention of overriding class Derived : Base { virtual void f( double) override final; };
105
string conversions conversion string ⇝ numeric type old C libraries
cannot convert ⇝ throw invalid_argument out_of_range #include <cstring> string s = "1234"; int i = atoi( s.c_str()); int i = ? istringstream ss(s); ss >> i; int i = stoi( s); int stoi( const string& s); unsigned long stoul double stod stoull, stof, stold string to_string( int i); string to_string( double d i);
106
cstdint signed unsigned intmax_t uintmax_t maximum width integer type
int8_t uint8_t / byte width exactly 8/16/32/64 bits Optional byte - C++17 int16_t uint16_t int32_t uint32_t int64_t uint64_t int_least8_t uint_least8_t smallest i. type with width of at least 8/16/32/64 bits int_least16_t uint_least16_t int_least32_t uint_least32_t int_least64_t uint_least64_t int_fast8_t uint_fast8_t fastest i. type with width of at least 8/16/32/64 bits int_fast16_t uint_fast16_t int_fast32_t uint_fast32_t int_fast64_t uint_fast64_t intptr_t uintptr_t integer type capable of holding a pointer nemusi nutne platit, ze byte === uint8_t ale vsude to (ted) plati
107
numeric_limits template
standardized way to query various properties of arithmetic types integer, real #include <limits> numeric_limits<int>::min() min max lowest digits digits10 is_signed is_integer is_exact is_specialized radix epsilon round_error min_exponent min_exponent10 max_exponent max_exponent10 has_infinity has_quiet_NaN has_signaling_NaN has_denorm has_denorm_loss infinity quiet_NaN signaling_NaN denorm_min is_iec559 is_bounded is_modulo traps tinyness_before round_style
108
bitset fixed-size set of bits optimalized access to individual bits
various forms of inicialization set, reset - set/reset of some/all bits bool all(), any(), none() - test unsigned x = 0xDEADBEEF; x &= 0xC0C0 << 2; #include <bitset> bitset<6> a(42); bitset<6> b(0x1B); bitset<18> c(" "); string s = "BaaBBaBaaBBaB"; bitset<4> d( s, 3, 4, 'a', 'B'); a ^= b; a[2] = (~b << 2)[3]; a.set(1); if( a.any()) ... from, count, what is 0/1
109
locale internacionalization support locale - set of facets
facet [fæsit] - ploška, stránka, aspekt, charakteristika třídy use_facet < numpunct<char> > (mylocale).decimal_point(); category facet member functions collate compare, hash, transform ctype is, narrow, scan_is, scan_not, tolower, toupper, widen codecvt always_noconv, encoding, in, length, max_length, out, unshift monetary moneypunct curr_symbol, decimal_point, frac_digits, grouping, negative_sign, neg_format, positive_sign, pos_format, thousands_sep money_get get money_put put numeric numpunct decimal_point, falsename, grouping, thousands_sep, truename num_get num_put time time_get date_order, get_date, get_monthname, get_time, get_weekday, get_year time_put messages close, get, open string comparison collate - string comparison string FormatNumber( long Number) { Currency const qty(Number); stringstream Convert; locale MyLocale( locale(), new GermanPunct() ); // Create customized locale Convert.imbue(MyLocale); // Imbue the custom locale to the stringstream Convert << showbase << fixed << qty; // Use some manipulators return Convert.str(); // Give the result to the string }
110
localization of char properties
locale C++03 C++11 void print_date( const Date& d) { switch( loc) { default: case ISO: cout << d.year() << "-" << d.month() << "/" << d.day(); break; case US: cout << d.month() << "/" << d.day() << "/" << d.year(); break; case CZ: cout << d.day() << "." << d.month() << "." << d.year(); break; } void print_date( const Date& d) { cout.imbue( locale{"en_US.UTF-8"}); cout << d; } stream localization template<class C> inline bool isalpha( C c, const locale& loc) { return use_facet< ctype<C> >(loc).is( alpha, c)); } localization of char properties sorting localization z < å locale dk{"da_DK"}; sort( v.begin(), v.end(), dk);
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.