the future of c++

29
© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israel www.sela.co.il The Future of C+ + Sasha Goldshtein CTO, SELA Group blog.sashag.net | @goldshtn

Upload: sasha-goldshtein

Post on 10-May-2015

8.035 views

Category:

Technology


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: The Future of C++

© Copyright SELA software & Education Labs Ltd. 14-18 Baruch Hirsch St.Bnei Brak 51202 Israelwww.sela.co.il

The Future of C++

Sasha GoldshteinCTO, SELA Group

blog.sashag.net | @goldshtn

Page 2: The Future of C++

Agenda

Variadic TemplatesConceptsOther Wild Ideas

Page 3: The Future of C++

Reminder: C++11 Compiler Support

• Visual Studio 2010: Some features are supported• Visual Studio 2012: Some more features are supported

• Comparison chart between many other compilers: http://s.sashag.net/rpST0u

Visu

al S

tudi

o 20

10 Automatic variables, decltypeRvalue referencesLambda functions

Visu

al S

tudi

o 20

12 Concurrency libraryMemory model

Not

sup

port

ed y

et Variadic templatesCustom literalsDelegating constructors

Page 4: The Future of C++

Variadic Templates

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

Page 5: The Future of C++

Variadic Templates

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 variable

foo(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;

Page 6: The Future of C++

Variadic Templates

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(vs)...);

≡ foo(goo(v1, v2, v3));≡ foo(goo(v1), goo(v2),

goo(v3));

Page 7: The Future of C++

How to Use Variadic Templates?

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

nothing

template <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

Page 8: The Future of C++

How to Use Variadic Templates?

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...));}

Page 9: The Future of C++

Reminder: Template Metaprogramming

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!

Page 10: The Future of C++

SFINAE (enable_if)

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) { printf("%p", t);}template <typename T> void print(const T& t, typename enable_if< is_convertible<T,string>::value, void* >::type dummy = nullptr) { printf("%s", string(t).c_str());}

template < bool, typename T = void>struct enable_if {};

template <typename T>struct enable_if<true,T> { typedef T type;};

From <type_traits> (simple specializations)

Page 11: The Future of C++

If That Was Easy…

We now develop a partial tuple<...>(Practically) No limit on number of type parametersFollowing A. Alexandrescu’s GoingNative 2012 talk

template <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};

Page 12: The Future of C++

Our Tuple’s Structure

• Note that tuple<T1,T2> derives from tuple<T2>

tuple<>(empty)

tuple<T1>

tuple<>(empty)

T1 _headtuple(T1 v): _head(v)

tuple<T2>

tuple<>(empty)

T2 _headtuple<T1,T2>T1 _head

tuple(T1 v, T2 v2): _head(v), tuple<T2>(v2)

Page 13: The Future of C++

Element Type

We need a way to declare the type of the k-th elementThe 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};

Page 14: The Future of C++

The get<N>() Function

template <int k, typename Ts...>typename enable_if<k==0, typename tuple_elem<k,Ts...>::type&>::typeget(tuple<Ts...>& tuple) { return tuple._head;} //base case

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}

Why not a member function on tuple?

Page 15: The Future of C++

Was It Worth It?

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() { ... }int number; bool flag;std::tie(number, flag) = get_something();//now number, flag are the unpacked tuple!

How does this work?tuple<T1&,T2&,

…>

Page 16: The Future of C++

Concepts: Why?

• Primary concern: improve compiler errors

• Secondary: optimizations, better specialization, etc.• Future feature: NOT PART OF C++ 11

In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_tree.h:65:0, from c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/map:60, from ConceptsMotivation.cpp:2:c:\mingw\bin\../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:\mingw\bin\../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 herec:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_function.h:236:22: error: no match for 'operator<' in '__x < __y'c:\mingw\bin\../lib/gcc/mingw32/4.6.2/include/c++/bits/stl_function.h:236:22: note: candidates are:c:\mingw\bin\../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:\mingw\bin\../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:\mingw\bin\../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:\mingw\bin\../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:\mingw\bin\../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:\mingw\bin\../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>&)

Page 17: The Future of C++

.NET Generic Constraints

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 constructor

class SortedList<T> where T : IComparable<T> { private T[] items; public void Add(T item) { //...can use item.CompareTo(otherItem) here }}

Page 18: The Future of C++

Proposed Syntax: Concept Definition

New keyword (concept)Looks like a template class with no implementation

auto 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&);};

Page 19: The Future of C++

Proposed Syntax: Concept Requirement

To assert that a concept is available, use requiresCan specialize templates on concept requirements

template <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) { ... }

Page 20: The Future of C++

Proposed Syntax: Concept Composition

Concepts can require other conceptsConcepts can derive from other concepts

concept 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};

Page 21: The Future of C++

Proposed Syntax: Concept Maps

Specify how to bind a concept to an existing typeE.g., vector<T> was not designed to adhere to a stack concept, but can be adapted after the fact

concept 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) { ... }};

Page 22: The Future of C++

Other Wild Ideas: static_if

• 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

Page 23: The Future of C++

Proposed static_if Syntax

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"); } }}

Page 24: The Future of C++

Proposed static_if Syntax

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) { ... }

Page 25: The Future of C++

Other Wild Ideas: Parallel Programming

Proposal N3361 based on Intel Cilkcilk_spawn, cilk_sync, cilk_for keywords

Akin to similar OpenMP pragmasAdditional suggestions for SIMD-friendly operators, such as array slices and #pragma simd

cilk_for (auto c = customers.begin(); c != customers.end(); ++c) { consider_vip_status(c); adjust_discount(c);}

Page 26: The Future of C++

Other Wild Ideas: Resumable Functions

Mirroring the success of C# 5’s await operatorBreaks down the method into a synchronous part and one or more continuations

future<vector<image*>> download_profile_images( vector<user> users) { vector<image*> images; webclient wc; for (const auto& user : users) images.push_back(new image( await wc.download(user.profile_image_url())); return images;}

Page 27: The Future of C++

Other Wild Ideas: STM

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); }}

Page 28: The Future of C++

Summary

Variadic TemplatesConceptsOther Wild IdeasMany more at the ISO C++ WG

Page 29: The Future of C++