The Future of C++


Published on

SELA C++ Conference session: The Future of C++, by Sasha Goldshtein.

Published in: Technology, Business
  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide
  • Not supported by VC11.To show the demo, use MinGW or any other gcc-clone (gcc 4.6.2 or higher is known to work).The quote (“dot dotdot is where the fun begins”) is from Andrei Alexandrescu’s talk at GoingNative 2012:
  • This is not up to date with the most recent proposal:
  • The Future of C++

    1. 1. © Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel
    2. 2. Variadic TemplatesConceptsOther Wild Ideas
    3. 3. • Visual Studio 2010: Some features are supported• Visual Studio 2012: Some more features are supported Not supported yet Visual Studio 2012 Visual Studio 2010 Automatic Concurrency Variadic variables, library templates decltype Memory Custom Rvalue model literals references Delegating Lambda constructors functions• Comparison chart between many other compilers:
    4. 4. The problem with existing templates is that the number of parameters is constant, consider: tuple, printf, other type-safe va_list, …template <typename T1> struct tuple { T1 first;};template <typename T1, typename T2> struct tuple { T1 first; T2 second;};template <typename T1, typename T2, typename T3> struct tuple { T1 first; T2 second; T3 third;};//VC11 <tuple> does this with macros, going up to 10 parameters
    5. 5. New syntax for unbounded type parameter lists and function parameter lists “Dot-dot-dot is where the fun begins”template <typename... Ts>void foo(Ts&&... vs); //note: Ts is NOT a type, vs is NOT a variablefoo(42); foo(5, "Hello, World", vector<int>());template <typename... Ts>struct tuple; //requires some serious work!tuple<int, float, string> tup(42, 42.0f, "42");get<1>(tup) += 3.0f; cout << get<2>(tup) << endl;
    6. 6. New syntax for type list expansion …and there’s also a new operator: sizeof...()template <typename... Ts>int passthrough_printf(const char* fmt, Ts&&... vs) return printf(fmt, vs...);}template <typename... Ts>class mixin : public Ts... {}; //will inherit from all Ts specified//note: the following two statements ARE NOT THE SAME!foo(goo(vs...)); ≡ foo(goo(v1, v2, v3));foo(goo(vs)...); ≡ foo(goo(v1), goo(v2), goo(v3));
    7. 7. Typically, you have a base case that does something (or nothing) and “recurse” to it from the variadic case Not true recursion (different template)template <typename... Ts>void print(Ts&&... vs) {} //base case, will match empty list, do nothingtemplate <typename T, typename... Ts>void print(T&& v, Ts&&... vs) { cout << v << endl; print(vs...); //”recursive” case; note that any decent compiler} //will inline the whole thing into the caller
    8. 8. Alternatively, the base case can be a bounded number of parameters to which we “recurse”template <typename T1, typename T2>bool assertContained(T1&& v1, T2&& v2) { return v1 == v2;}template <typename T1, typename T2, typename... Ts>bool assertContained(T1&& v1, T2&& v2, Ts&&... vs) { return (v1 == v2 || assertContained(v1, vs...));}
    9. 9. Using the compiler’s template mechanism to do work at compile-time Theorem: C++ templates are Turing-complete//recursive case:template <int N> struct fibo { static const int value = fibo<N-1>::value + fibo<N-2>::value;};//base cases:template <> struct fibo<0> { static const int value = 1; };template <> struct fibo<1> { static const int value = 1; };cout << fibo<14>::value; //compile-time!
    10. 10. template <typename T> void print(const T& t) {}template <typename T> void print(const T& t, typename enable_if< is_pointer<T>::value, void* >::type dummy = nullptr) { From <type_traits> printf("%p", t); (simple specializations)}template <typename T> void print(const T& t, typename enable_if< is_convertible<T,string>::value, void* template < bool, typename T = void >::type dummy = nullptr) { > printf("%s", string(t).c_str()); struct enable_if {};} template <typename T> struct enable_if<true,T> { typedef T type; };
    11. 11. We now develop a partial tuple<...> (Practically) No limit on number of type parameters Following A. Alexandrescu’s GoingNative 2012 talktemplate <typename... Ts> struct tuple {};template <typename T, typename... Ts>struct tuple : private tuple<Ts...> { T _head;public: tuple(T&& v, Ts&&... vs) : _head(v), tuple<Ts...>(vs...) {} //many more methods omitted};
    12. 12. • Note that tuple<T1,T2> derives from tuple<T2> tuple<> tuple<> tuple<> (empty) (empty) (empty) tuple<T1> tuple<T2> T1 _head T2 _head tuple(T1 v): tuple<T1,T2> _head(v) T1 _head tuple(T1 v, T2 v2): _head(v), tuple<T2>(v2)
    13. 13. We need a way to declare the type of the k-th element The get<N>() method will return it (later)template <int, typename> struct tuple_elem;template <typename T, typename... Ts>struct tuple_elem<0, tuple<T,Ts...>> { typedef T type; //this is the head, base case};template <int k, typename T, typename Ts...>struct tuple_elem<k, tuple<T,Ts...>> { typedef tuple_elem<k-1,Ts...>::type type; //recursion};
    14. 14. template <int k, typename Ts...>typename enable_if<k==0, typename tuple_elem<k,Ts...>::type&>::typeget(tuple<Ts...>& tuple) { return tuple._head; Why not a member} //base case function on tuple?template <int k, typename T, typename Ts...>typename enable_if<k!=0, typename tuple_elem<k,T,Ts...>::type&>::typeget(tuple<T,Ts...>& tuple) { tuple<Ts...>& base = tuple; get<k-1>(base); //recursion}
    15. 15. tuple<int, float, string, employee> tup(...);get<0>(tup) = 42;get<3>(tup) = employee("John");cout << get<3>(tup).name() << endl;//Worth the effort. C# doesn’t have unlimited tuples!//…and here’s another cool thing, Python-style:tuple<int,bool> get_something() { ... } How does this work?int number; bool flag; tuple<T1&,T2&,…>std::tie(number, flag) = get_something();//now number, flag are the unpacked tuple!
    16. 16. • Primary concern: improve compiler errors In file included from c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_tree.h:65:0, from c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/map:60, from ConceptsMotivation.cpp:2: c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_function.h: In member function bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = non_comparable]: c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_map.h:452:2: instantiated from std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = non_comparable, _Tp = int, _Compare = std::less<non_comparable>, _Alloc = std::allocator<std::pair<const non_comparable, int> >, std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int, std::map<_Key, _Tp, _Compare, _Alloc>::key_type = non_comparable] ConceptsMotivation.cpp:8:20: instantiated from here c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_function.h:236:22: error: no match for operator< in __x < __y c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_function.h:236:22: note: candidates are: c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_pair.h:207:5: note: template<class _T1, class _T2> bool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_iterator.h:291:5: note: template<class _Iterator> bool std::operator<(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&) c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_iterator.h:341:5: note: template<class _IteratorL, class _IteratorR> bool std::operator<(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&) c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_tree.h:856:5: note: template<class _Key, class _Val, class _KeyOfValue, class _Compare, class _Alloc> bool std::operator<(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&, const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&) c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_map.h:894:5: note: template<class _Key, class _Tp, class _Compare, class _Alloc> bool std::operator<(const std::map<_Key, _Tp, _Compare, _Alloc>&, const std::map<_Key, _Tp, _Compare, _Alloc>&) c:mingwbin../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_multimap.h:812:5: note: template<class _Key, class _Tp, class _Compare, class _Alloc> bool std::operator<(const std::multimap<_Key, _Tp, _Compare, _Alloc>&, const std::multimap<_Key, _Tp, _Compare, _Alloc>&)• Secondary: optimizations, better specialization, etc.• Future feature: NOT PART OF C++ 11
    17. 17. The language compiler verifies that the generic type performs only operations that are guaranteed to exist on its type parameters Limited set of constraints: base class, interface, parameterless constructorclass SortedList<T> where T : IComparable<T> { private T[] items; public void Add(T item) { //...can use item.CompareTo(otherItem) here }}
    18. 18. New keyword (concept) Looks like a template class with no implementationauto concept CopyConstructible<typename T> { T(const T&);};auto concept Comparable<typename T> { bool operator<(T, T);};auto concept Convertible<typename T, typename S> { operator S(const T&);};
    19. 19. To assert that a concept is available, use requires Can specialize templates on concept requirementstemplate <typename T> requires LessThanComparable<T>void sort(T* data, int length) { ... }//instead of SFINAE:template <typename T> requires !LessThanComparable<T> && GreaterThanComparable<T>void sort(T* data, int length) { ... }
    20. 20. Concepts can require other concepts Concepts can derive from other conceptsconcept InputIterator<typename Iter, typename Elem> { requires CopyConstructible<Iter>; Elem operator*(const Iter&); Iter operator++(Iter&, int);};concept ForwardIterator<typename Iter, typename Elem> : InputIterator<Iter, Value> { //additional requirements};
    21. 21. Specify how to bind a concept to an existing type E.g., vector<T> was not designed to adhere to a stack concept, but can be adapted after the factconcept stack<typename C, typename T> { void push(C&, const T&); bool pop(C&, T&);};template <typename T> concept_map stack<vector<T>> { void push(vector<T>& v, const T& t) { v.push_back(t); } bool pop(vector<T>& v, T& t) { ... }};
    22. 22. • enable_if “[…] is marred by a baroque syntax, frequent and nontrivial corner cases, and interference of mechanism with the exposed interface.” – N3329 (draft proposal for static_if)• Currently impossible to: – Define a class member conditionally – Easily share code between specializations – Mix case-specific code within the same function
    23. 23. template <typename T>void print(const T& t) { static_if (is_integral<T>::value) { printf("%d", (unsigned long long)t); } else { static_if (is_pointer<T>::value) { printf("%p", t); } else { static_assert(false, "Unsupported type"); } }}
    24. 24. template <int N>struct factorial { //remember fibo? static_if (N <= 1) { enum { value = 1 }; } else { enum { value = factorial<N-1>::value * N }; }};//can replace many uses of concepts:template <typename T> void sort(...)if (has_operator_less_than<T>::value) { ... }
    25. 25. Proposal N3361 based on Intel Cilk cilk_spawn, cilk_sync, cilk_for keywords Akin to similar OpenMP pragmas Additional suggestions for SIMD-friendly operators, such as array slices and #pragma simdcilk_for (auto c = customers.begin(); c != customers.end(); ++c) { consider_vip_status(c); adjust_discount(c);}
    26. 26. Mirroring the success of C# 5’s await operator Breaks down the method into a synchronous part and one or more continuationsfuture<vector<image*>> download_profile_images( vector<user> users) { vector<image*> images; webclient wc; for (const auto& user : users) images.push_back(new image( await; return images;}
    27. 27. Transactional language constructs on top of software transactional memory (N3341) (By the way, Intel Haswell will have hardware TX semantics)class Account { void withdraw(int amount) { __transaction { balance -= amount; } }};void transfer(Account& a, Account& b, int amount) { __transaction { a.withdraw(amount); b.deposit(amount); }}
    28. 28. Variadic TemplatesConceptsOther Wild IdeasMany more at the ISO C++ WG
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.