SlideShare une entreprise Scribd logo
1  sur  108
Télécharger pour lire hors ligne
Writing good std::future<C++>
Anton Bikineev, 2016
C++17 Standardization process.
What we wanted and expected…
• concepts
• ranges
• modules
• parallel algorithms
• .then on futures and other
concurrency features
• executors
• coroutines with await
• transactional memory
• contracts
• fold expressions
• uniform function call
syntax
• constexpr lambdas
• filesystem library
• networking library
• library features, e.g. any,
optional, etc…
• etc…
Writing good std::future<C++>
• concepts
• ranges
• modules
• parallel algorithms
• .then on futures and other
concurrency features
• executors
• coroutines with await
• transactional memory
• contracts
• fold expressions
• uniform function call
syntax
• constexpr lambdas
• filesystem library
• networking library
• library features, e.g. any,
optional, etc…
• etc…
C++17 Standardization process.
What we’ve got.
Writing good std::future<C++>
• concepts
• ranges
• modules
• parallel algorithms
• .then on futures and other
concurrency features
• executors
• coroutines with await
• transactional memory
• contracts
• fold expressions
• uniform function call
syntax
• constexpr lambdas
• filesystem library
• networking library
• library features, e.g. any,
optional, etc…
• etc…
C++17 Standardization process.
What we’ve got.
Kenny Kerr @kennykerr 7 march

C++11 attempted too much. C++14 fixed that.

C++17 attempts too little. We need to fix that.
Writing good std::future<C++>
Writing good std::future<C++>
C++’s view on polymorphism
Writing good std::future<C++>
C++’s view on polymorphism
class Factory
{
public:
virtual AbstractButton* createButton() = 0;
};
Writing good std::future<C++>
C++’s view on polymorphism
class Factory
{
public:
virtual std::unique_ptr<AbstractButton> createButton() = 0;
};
Writing good std::future<C++>
C++’s view on polymorphism
class Factory
{
public:
virtual std::unique_ptr<AbstractButton> createButton() = 0;
};
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
Writing good std::future<C++>
C++’s view on polymorphism
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
Writing good std::future<C++>
C++’s view on polymorphism
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
Writing good std::future<C++>
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
<members>
Writing good std::future<C++>
ConcreteFactory
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
<members>
movq %rsp, %rbp
Writing good std::future<C++>
ConcreteFactory
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
<members>
factory
-24
movq %rdi, -24(%rbp)
Writing good std::future<C++>
ConcreteFactory
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
<members>
factory
-24
movq -24(%rbp), %rax
Writing good std::future<C++>
ConcreteFactory
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
factory
-24
<members>
vptr
<ptrs to funs>
&createButton
Writing good std::future<C++>
ConcreteFactory
vtable
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
factory
-24
<members>
vptr
<ptrs to funs>
&createButton
movq (%rax), %rax
Writing good std::future<C++>
ConcreteFactory
vtable
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
the function itself
factory
-24
<members>
vptr
<ptrs to funs>
&createButton
addq $8, %rax
Writing good std::future<C++>
ConcreteFactory
vtable
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
<members>
vptr
<ptrs to funs>
&createButton
factory
-24
the function itself
movq (%rax), %rax
Writing good std::future<C++>
ConcreteFactory
vtable
Dynamic polymorphism
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
<members>
vptr
<ptrs to funs>
&createButton
factory
-24
the function itselfcall %rax
Writing good std::future<C++>
ConcreteFactory
vtable
Dynamic polymorphism overhead
rsp
createForm frame
rbp
rdi
rax
x86_64 registers
…
<local vars, ra>
ConcreteFactory
<members>
vptr
vtable
<ptrs to funs>
&createButton
factory
-24
the function itself
Writing good std::future<C++>
C++ templates — solution?
template <class Factory>
void createForm(Factory& factory)
{
auto button = factory.createButton();
}
Writing good std::future<C++>
C++ templates — solution?
template <class Factory>
void createForm(Factory& factory)
{
auto button = factory.createButton();
}
template void createForm(ConcreteFactory&);
Writing good std::future<C++>
C++ static interface. CRTP
template <class Impl>
struct Factory
{
std::unique_ptr<AbstractButton> createButton()
{
return static_cast<Impl*>(this)->createButton();
}
};
Writing good std::future<C++>
C++ static interface. CRTP
template <class Impl>
struct Factory
{
std::unique_ptr<AbstractButton> createButton()
{
return static_cast<Impl*>(this)->createButton();
}
};
struct ConcreteFactory: Factory<ConcreteFactory>
{
std::unique_ptr<AbstractButton> createButton()
{
return std::make_unique<ConcreteButton>();
}
};
Writing good std::future<C++>
C++ static interface. Usage
template <class Impl>
void createForm(Factory<Impl>& fact)
{
auto button = fact.createButton();
}
template void createForm(Factory<ConcreteFactory>&);
Writing good std::future<C++>
CRTP problems
• looks like a hack;
• no possibility to get nested types from Impl;
• Impl is incomplete at point of instantiation.
Writing good std::future<C++>
Concepts — solution?
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
Writing good std::future<C++>
Concepts — solution?
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
template <class T>
requires factory<T>
void createForm(T& fact)
{
auto button = fact.createButton();
}
Writing good std::future<C++>
Concepts — solution?
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
template <factory T>
void createForm(T& fact)
{
auto button = fact.createButton();
}
Writing good std::future<C++>
Concepts — solution?
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
factory{T}
void createForm(T& fact)
{
auto button = fact.createButton();
}
Writing good std::future<C++>
Concepts — solution?
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
void createForm(factory& fact)
{
auto button = fact.createButton();
}
Writing good std::future<C++>
Defining concepts
template <class T>
concept bool variable_concept = constraint-expression;
template <class T>
concept bool function_concept()
{
return constraint-expression;
}
Writing good std::future<C++>
Defining concepts. Type traits
template <class T>
concept bool integral = std::is_integral<T>::value;
Writing good std::future<C++>
Defining concepts. Type traits
template <class T>
concept bool integral = std::is_integral<T>()();
Writing good std::future<C++>
Defining concepts. Type traits
// from library fundamentals TS
namespace std::experimental
{
template <class T>
constexpr bool is_integral_v = is_integral<T>::value;
}
namespace stde = std::experimental;
template <class T>
concept bool integral = stde::is_integral_v<V>;
Writing good std::future<C++>
Concepts. Iterator example
Writing good std::future<C++>
Concepts. Iterator example
template <class T>
concept bool iterator = ...;
Writing good std::future<C++>
Concepts. Iterator example
template <class T>
concept bool swappable = requires (T t)
{
{std::swap(t, t)} -> void;
}
or requires (T t)
{
// for ADL
{swap(t, t)} -> void;
};
Writing good std::future<C++>
Concepts. Iterator example
template <class T>
concept bool iterator = stde::is_copy_constructible_v<T>
and stde::is_copy_assignable_v<T>
and stde::is_destructible_v<T>
and swappable<T>
and requires (T r)
{
*r;
{++r} -> T&;
};
Writing good std::future<C++>
Concepts. Input iterator
template <class T>
concept bool equality_comparable = requires (T t)
{
{t == t} -> bool;
};
template <class T>
concept bool input_iterator = iterator<T>
and equality_comparable<T>;
Writing good std::future<C++>
Concepts. Forward iterator
Writing good std::future<C++>
Concepts. Forward iterator
template <class T>
concept bool forward_iterator = input_iterator<T>
and stde::is_default_constructible_v<T>
and requires (T r)
{
{r++} -> const T&;
};
Writing good std::future<C++>
Concepts. Bidirectional iterator
template <class T>
concept bool bidirectional_iterator = forward_iterator<T>
and requires (T r)
{
{--r} -> T&
{r--} -> const T&;
};
Writing good std::future<C++>
Concepts. Random access iterator
template <class T>
concept bool random_access_iterator = bidirectional_iterator<T>
and requires (T it,
typename std::iterator_traits<T>::difference_type n)
{
{it += n} -> T&;
{it + n} -> T;
{n + it} -> T;
{it -= n} -> T&;
{it - it} ->
typename std::iterator_traits<T>::difference_type;
{it[n]} ->
typename std::iterator_traits<T>::reference;
{it < it} -> bool;
{it <= it} -> bool;
{it > it} -> bool;
{it >= it} -> bool;
};
Concepts. Random access iterator
static_assert(forward_iterator<
std::forward_list<int>::iterator>);
Concepts. Iterators. Let’s test!
Writing good std::future<C++>
static_assert(forward_iterator<
std::forward_list<int>::iterator>);
static_assert(bidirectional_iterator<
std::list<int>::iterator>);
static_assert(bidirectional_iterator<
std::map<char, int>::iterator>);
Concepts. Iterators. Let’s test!
Writing good std::future<C++>
static_assert(forward_iterator<
std::forward_list<int>::iterator>);
static_assert(bidirectional_iterator<
std::list<int>::iterator>);
static_assert(bidirectional_iterator<
std::map<char, int>::iterator>);
static_assert(random_access_iterator<int*>);
static_assert(random_access_iterator<
std::vector<int>::iterator>);
static_assert(random_access_iterator<
std::deque<int>::iterator>);
Concepts. Iterators. Let’s test!
Writing good std::future<C++>
C++ generic programming and TMP
Writing good std::future<C++>
template <class _InputIterator>
vector(_InputIterator __first,
typename enable_if<
__is_input_iterator<_InputIterator>::value &&
!__is_forward_iterator<_InputIterator>::value &&
is_constructible<
value_type,
typename iterator_traits<
_InputIterator>::reference>::value,
_InputIterator>::type __last);
template <class _ForwardIterator>
vector(_ForwardIterator __first,
typename enable_if<
__is_forward_iterator<_ForwardIterator>::value &&
is_constructible<
value_type,
typename iterator_traits<
_ForwardIterator>::reference>::value,
_ForwardIterator>::type __last);
Without concepts: libc++
Writing good std::future<C++>
vector(input_iterator __first, input_iterator __last);
vector(forward_iterator __first, forward_iterator __last);
With concepts: libc++
Writing good std::future<C++>
That’s it!
The greediness of T&&
Writing good std::future<C++>
// from Meyers’s EMC++ Item 26
std::multiset<std::string> names;
void logAndAdd(const std::string& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(name);
}
The greediness of T&&
Writing good std::future<C++>
// from Meyers’s EMC++ Item 26
std::multiset<std::string> names;
void logAndAdd(const std::string& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(name);
}
std::string petName("Darla");
logAndAdd(petName); // 1)
logAndAdd(std::string("Persephone")); // 2)
logAndAdd("Patty Dog”); // 3)
The greediness of T&&
Writing good std::future<C++>
// from Meyers’s EMC++ Item 26
std::multiset<std::string> names;
void logAndAdd(const std::string& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(name);
}
std::string petName("Darla");
logAndAdd(petName); // 1) okay, just copying
logAndAdd(std::string("Persephone")); // 2) extra copy
logAndAdd("Patty Dog”); // 3) no need to copy or move
The greediness of T&&
Writing good std::future<C++>
The greediness of T&&
// from Meyers’s EMC++ Item 26
template <typename T>
void logAndAdd(T&& name)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(std::forward<T>(name));
}
std::string petName("Darla");
logAndAdd(petName); // 1) okay, just copying
logAndAdd(std::string("Persephone")); // 2) moving!
logAndAdd("Patty Dog”); // 3) neither moving nor copying,
// just creating inplaceWriting good std::future<C++>
// from Meyers’s EMC++ Item 26
std::string nameFromIdx(int idx);
void logAndAdd(int idx)
{
auto now = std::chrono::system_clock::now();
log(now, "logAndAdd");
names.emplace(nameFromIdx(idx));
}
short nameIdx;
logAndAdd(nameIdx); // error!
The greediness of T&&
Writing good std::future<C++>
Meyers, “Effective Modern C++”,
Item 26:
Avoid overloading on universal references.
The greediness of T&&
Writing good std::future<C++>
Meyers, “Effective Modern C++”,
Item 26:
Avoid overloading on universal references.
...
The greediness of T&&
Writing good std::future<C++>
Meyers, “Effective Modern C++”,
Item 26:
Avoid overloading on universal references.
...
but not on constrained universal references!
The greediness of T&&
Writing good std::future<C++>
void logAndAdd(int idx);
template <typename T>
void logAndAdd(T&& name)
{
...
names.emplace(std::forward<T>(name));
}
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
void logAndAdd(int idx);
template <typename T, typename =
std::enable_if_t<
stde::is_convertible_v<
T, std::string>>>
void logAndAdd(T&& name)
{
...
names.emplace(std::forward<T>(name));
}
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
void logAndAdd(int idx);
template <typename T, typename =
std::enable_if_t<
stde::is_convertible_v<
std::remove_reference_t<T>, std::string>>>
void logAndAdd(T&& name)
{
...
names.emplace(std::forward<T>(name));
}
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
void logAndAdd(int idx);
template <typename T, typename =
std::enable_if_t<
stde::is_convertible_v<
std::remove_reference_t<T>, std::string>>>
void logAndAdd(T&& name)
{
...
names.emplace(std::forward<T>(name));
}
short nameIdx;
logAndAdd(nameIdx); // calls logAndAdd(int) just fine!
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
template <class From, class To>
concept bool convertible =
stde::is_convertible_v<
std::remove_reference_t<From>, To>;
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
template <class From, class To>
concept bool convertible =
stde::is_convertible_v<
std::remove_reference_t<From>, To>;
void logAndAdd(convertible<std::string>&& name)
{
...
names.emplace(std::forward<decltype(name)>(name));
}
short nameIdx;
logAndAdd(nameIdx); // calls logAndAdd(int) just fine!
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
// from Meyers’s EMC++ Item 26
class Person {
public:
template <typename T>
explicit Person(T&& n) // perfect forwarding ctor
: name(std::forward<T>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
private:
std::string name;
};
Constrained T&&
as the best parameter type for efficiency and safety
Writing good std::future<C++>
// from Meyers’s EMC++ Item 26
class Person {
public:
template <typename T>
explicit Person(T&& n) // perfect forwarding ctor
: name(std::forward<T>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
private:
std::string name;
};
Person p("Nancy");
auto cloneOfP(p); // WOW!
Constrained T&&
as the best parameter type for efficiency and safety
// from Meyers’s EMC++ Item 26
class Person {
public:
explicit Person(convertible<std::string>&& n)
: name(std::forward<decltype(n)>(n)) {}
explicit Person(int idx)
: name(nameFromIdx(idx)) {}
private:
std::string name;
};
Person p("Nancy");
auto cloneOfP(p); // now works fine!
Constrained T&&
as the best parameter type for efficiency and safety
std::future<C++> example:
flat_map
Writing good std::future<C++>
namespace boost::container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class Allocator =
std::allocator<std::pair<Key, Value>>>
class flat_map;
}
C++17 example: boost::flat_map
Writing good std::future<C++>
namespace mine::container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, Value>>>
class flat_map;
}
C++17 example: my flat_map
Writing good std::future<C++>
namespace mine::container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, Value>>>
requires default_constructible<Value>
class flat_map;
}
C++17 example: my flat_map
Writing good std::future<C++>
namespace mine::container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, Value>>>
requires default_constructible<Value>
and random_access_iterator<
typename UnderlyingContainer::iterator>
class flat_map;
}
C++17 example: my flat_map
Writing good std::future<C++>
namespace mine::container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, Value>>>
requires default_constructible<Value>
and random_access_iterator<
typename UnderlyingContainer::iterator>
and requires (Compare cmp, Key key)
{
{cmp(key, key)} -> bool;
}
class flat_map;
}
C++17 example: my flat_map
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using key_type = Key;
using mapped_type = Value;
using underlying_type = UnderlyingContainer;
using typename underlying_type::value_type;
static_assert(stde::is_same_v<value_type,
std::pair<key_type, mapped_type>>);
using key_compare = Compare;
using value_compare = struct {
...
};
};
flat_map: typedefs
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using value_compare = struct {
bool operator()(const value_type& left,
const value_type& right) const {
return key_compare()(left.first, right.first);
}
bool operator()(const key_type& left,
const value_type& right) const {
return key_compare()(left, right.first);
}
bool operator()(const value_type& left,
const key_type& right) const {
return key_compare()(left.first, right);
}};
};
flat_map: typedefs
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using typename underlying_type::size_type;
using typename underlying_type::difference_type;
using typename underlying_type::allocator_type;
using typename underlying_type::reference;
using typename underlying_type::const_reference;
using typename underlying_type::pointer;
using typename underlying_type::const_pointer;
using typename underlying_type::iterator;
using typename underlying_type::const_iterator;
using typename underlying_type::reverse_iterator;
using typename underlying_type::const_reverse_iterator;
};
flat_map: typedefs
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using underlying_type::begin; // laconic wrapping
using underlying_type::cbegin;
using underlying_type::end;
using underlying_type::cend;
using underlying_type::rbegin;
using underlying_type::crbegin;
using underlying_type::rend;
using underlying_type::crend;
};
flat_map: laconic wrapping
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using underlying_type::swap;
using underlying_type::clear;
using underlying_type::empty;
using underlying_type::size;
using underlying_type::max_size;
using underlying_type::capacity;
using underlying_type::reserve;
using underlying_type::shrink_to_fit;
};
flat_map: laconic wrapping
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
flat_map() = default;
template <class Iterator>
flat_map(Iterator first, Iterator last):
underlying_type{first, last}
{
std::sort(begin(), end());
}
flat_map(std::initializer_list<value_type> list):
flat_map{list.begin(), list.end()}
{
}
};
flat_map: ctors
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
flat_map() = default;
flat_map(input_iterator first, input_iterator last):
underlying_type{first, last}
{
std::sort(begin(), end());
}
flat_map(std::initializer_list<value_type> list):
flat_map{list.begin(), list.end()}
{
}
};
flat_map: ctors
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
flat_map() = default;
flat_map(input_iterator first, input_iterator last):
underlying_type{first, last}
{
stde::sort(stde::par, begin(), end());
}
flat_map(std::initializer_list<value_type> list):
flat_map{list.begin(), list.end()}
{
}
};
flat_map: ctors
Writing good std::future<C++>
namespace detail
{
template <class Iterator, class Key, class Compare>
Iterator binary_search(Iterator begin,
Iterator end,
const Key& key,
const Compare& cmp)
{
auto it = std::lower_bound(begin, end, key, cmp);
if (it == end || cmp(key, *it))
return end;
return it;
}
}
flat_map: binary_search
Writing good std::future<C++>
namespace detail
{
auto binary_search(forward_iterator begin,
forward_iterator end,
const auto& key,
const auto& cmp)
{
auto it = std::lower_bound(begin, end, key, cmp);
if (it == end || cmp(key, *it))
return end;
return it;
}
}
flat_map: binary_search
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
iterator find(const key_type& key)
{
return detail::binary_search(
begin(), end(), key, value_compare{});
}
const_iterator find(const key_type& key) const
{
return detail::binary_search(
cbegin(), cend(), key, value_compare{});
}
};
flat_map: find
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
mapped_type& at(const key_type& key)
{
const auto it = find(key);
if (it == end()) throw std::range_error(“no key”);
return it->second;
}
const mapped_type& at(const key_type& key) const
{
// same as above
}
};
flat_map: at
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
std::pair<iterator, bool> emplace(
auto&& first, auto&&... args)
{
value_compare comp;
const auto it = std::lower_bound(
begin(), end(), first, comp);
if (it == end() || comp(first, *it))
return {underlying_type::emplace(it,
std::forward<decltype(first)>(first),
std::forward<decltype(args)>(args)...),
true};
return {it, false};
}
};
flat_map: emplace
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
std::pair<iterator, bool> insert(const value_type& value)
{
return emplace(value);
}
};
flat_map: insert
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
std::pair<iterator, bool> insert(const value_type& value)
{
return emplace(value);
}
std::pair<iterator, bool> insert(value_type&& value)
{
return emplace(std::move(value));
}
};
flat_map: insert
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
std::pair<iterator, bool> insert(
convertible<value_type>&& value)
{
return emplace(std::forward<decltype(value)>(value));
}
// no need to provide anything else!
};
flat_map: insert
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
void insert(input_iterator first,
input_iterator last)
{
const auto count = std::distance(first, last);
const auto room = capacity() - size();
if (room < count)
reserve(size() + count);
for (; first != last; ++first)
emplace(*first);
}
};
flat_map: insert
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
void insert(std::initializer_list<value_type> list)
{
insert(list.begin(), list.end());
}
};
flat_map: insert
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
mapped_type& operator[](convertible<key_type>&& key)
{
return emplace(
std::forward<decltype(key)>(key),
mapped_type{}
).first->second;
}
};
flat_map: index operator
Writing good std::future<C++>
template <...>
class flat_map final: private UnderlyingContainer
{
using underlying_type::erase;
size_type erase(const key_type& key)
{
const auto it = find(key);
if (it == end())
return 0u;
erase(it);
return 1u;
}
};
flat_map: erase
Writing good std::future<C++>
Modularizing flat_map. Interface
Writing good std::future<C++>
// flat_map.hpp
#include <...>
namespace container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, T>>>
class flat_map
{
...
};
}
Modularizing flat_map. Interface
Writing good std::future<C++>
// flat_map.ixx
#include <...>
module container.flat_map;
export namespace container
{
template <class Key, class Value,
class Compare = std::less<Key>,
class UnderlyingContainer =
std::vector<std::pair<Key, T>>>
class flat_map
{
...
};
}
Modularizing flat_map. Consuming
Writing good std::future<C++>
// main.cpp
import std.io;
import container.flat_map;
int main()
{
container::flat_map<std::string, int> map =
{{"second", 2}, {"first", 1}, {"third", 3}};
for (const auto& p: map)
std::cout << p.first << ": " << p.second << std::endl;
return 0;
}
Some more slides…
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> std::unique_ptr<AbstractButton>;
};
void createForm(factory& fact)
{
auto button = fact.createButton();
}
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
struct AbstractButton
{
virtual void onClick(std::function<void ()>) = 0;
virtual void onMove (std::function<void ()>) = 0;
};
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
namespace detail // or std? or whatever
{
constexpr auto empty = [](auto...){};
}
template <class T>
concept bool button = requires (T t)
{
t.onClick(detail::empty);
t.onMove(detail::empty);
};
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
template <class T>
concept bool button = ...;
template <class T>
concept bool factory = requires (T t)
{
{t.createButton()} -> button;
};
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
class TButton
{
void onClick(...);
void onMove(...);
};
class QPushButton
{
void onClick(...);
void onMove(...);
};
Writing good std::future<C++>
Static polymorphism with concepts.
Improving
class TButton
{
void onClick(...);
void onMove(...);
};
class QPushButton
{
void onClick(...);
void onMove(...);
};
class VCLFactory
{
TButton createButton()
{
return TButton{};
}
};
class QtFactory
{
QPushButton createButton()
{
return QPushButton{};
}
};
Writing good std::future<C++>
Static polymorphism with concepts.
Using
void createForm(factory& fact)
{
auto button = fact.createButton();
button.onClick([]{ /* pum pum pum */ });
}
int main()
{
QtFactory factory;
createForm(factory);
QApplication::run();
}
Writing good std::future<C++>
Writing good std::future<C++>
Thank you for your attention!

Contenu connexe

Tendances

Javascript Styles and some tips
Javascript Styles and some tipsJavascript Styles and some tips
Javascript Styles and some tipsVítor Baptista
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Phil Calçado
 
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17LogeekNightUkraine
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...Phil Calçado
 
Solid C++ by Example
Solid C++ by ExampleSolid C++ by Example
Solid C++ by ExampleOlve Maudal
 
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip CalçadoJustjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip CalçadoPaulo Silveira
 
Introduction to Programming Bots
Introduction to Programming BotsIntroduction to Programming Bots
Introduction to Programming BotsDmitri Nesteruk
 
Let's refine your Scala Code
Let's refine your Scala CodeLet's refine your Scala Code
Let's refine your Scala CodeTech Triveni
 
Javascript engine performance
Javascript engine performanceJavascript engine performance
Javascript engine performanceDuoyi Wu
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesAndrey Karpov
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)Yeshwanth Kumar
 
Understanding Javascript Engines
Understanding Javascript Engines Understanding Javascript Engines
Understanding Javascript Engines Parashuram N
 
TypeScript Presentation - Jason Haffey
TypeScript Presentation - Jason HaffeyTypeScript Presentation - Jason Haffey
TypeScript Presentation - Jason HaffeyRalph Johnson
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerAndrey Karpov
 
GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)Huy Do
 
Dr archana dhawan bajaj - csharp fundamentals slides
Dr archana dhawan bajaj - csharp fundamentals slidesDr archana dhawan bajaj - csharp fundamentals slides
Dr archana dhawan bajaj - csharp fundamentals slidesDr-archana-dhawan-bajaj
 
The operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerThe operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerAndrey Karpov
 

Tendances (20)

Javascript Styles and some tips
Javascript Styles and some tipsJavascript Styles and some tips
Javascript Styles and some tips
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
Vladymyr Bahrii Understanding polymorphism in C++ 16.11.17
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
 
Solid C++ by Example
Solid C++ by ExampleSolid C++ by Example
Solid C++ by Example
 
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip CalçadoJustjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
Justjava 2007 Arquitetura Java EE Paulo Silveira, Phillip Calçado
 
Introduction to Programming Bots
Introduction to Programming BotsIntroduction to Programming Bots
Introduction to Programming Bots
 
Let's refine your Scala Code
Let's refine your Scala CodeLet's refine your Scala Code
Let's refine your Scala Code
 
Javascript engine performance
Javascript engine performanceJavascript engine performance
Javascript engine performance
 
Best Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' MistakesBest Bugs from Games: Fellow Programmers' Mistakes
Best Bugs from Games: Fellow Programmers' Mistakes
 
Monte Carlo C++
Monte Carlo C++Monte Carlo C++
Monte Carlo C++
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
Google Dart
Google DartGoogle Dart
Google Dart
 
Understanding Javascript Engines
Understanding Javascript Engines Understanding Javascript Engines
Understanding Javascript Engines
 
TypeScript Presentation - Jason Haffey
TypeScript Presentation - Jason HaffeyTypeScript Presentation - Jason Haffey
TypeScript Presentation - Jason Haffey
 
What's new in c#7
What's new in c#7What's new in c#7
What's new in c#7
 
C++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical ReviewerC++ Code as Seen by a Hypercritical Reviewer
C++ Code as Seen by a Hypercritical Reviewer
 
GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)GOCON Autumn (Story of our own Monitoring Agent in golang)
GOCON Autumn (Story of our own Monitoring Agent in golang)
 
Dr archana dhawan bajaj - csharp fundamentals slides
Dr archana dhawan bajaj - csharp fundamentals slidesDr archana dhawan bajaj - csharp fundamentals slides
Dr archana dhawan bajaj - csharp fundamentals slides
 
The operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzerThe operation principles of PVS-Studio static code analyzer
The operation principles of PVS-Studio static code analyzer
 

Similaire à Writing good std::future&lt;c++>

Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Sergey Platonov
 
Overview of C++20 and a deeper look into modules
Overview of C++20 and a deeper look into modulesOverview of C++20 and a deeper look into modules
Overview of C++20 and a deeper look into modulesmmeisenzahl
 
Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)Angel Boy
 
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...HostedbyConfluent
 
JavaScript Robotics
JavaScript RoboticsJavaScript Robotics
JavaScript RoboticsAnna Gerber
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical softwarePVS-Studio
 
C++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIAC++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIADheeraj Kataria
 
Learn c++ Programming Language
Learn c++ Programming LanguageLearn c++ Programming Language
Learn c++ Programming LanguageSteve Johnson
 
C# What's next? (7.x and 8.0)
C# What's next? (7.x and 8.0)C# What's next? (7.x and 8.0)
C# What's next? (7.x and 8.0)Christian Nagel
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++NextSergey Platonov
 
Auto cad 2006_api_overview
Auto cad 2006_api_overviewAuto cad 2006_api_overview
Auto cad 2006_api_overviewscdhruv5
 
Connecting C++ and JavaScript on the Web with Embind
Connecting C++ and JavaScript on the Web with EmbindConnecting C++ and JavaScript on the Web with Embind
Connecting C++ and JavaScript on the Web with EmbindChad Austin
 
Programming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptxProgramming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptxNoorAntakia
 
C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 Sumant Tambe
 

Similaire à Writing good std::future&lt;c++> (20)

Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
 
Overview of C++20 and a deeper look into modules
Overview of C++20 and a deeper look into modulesOverview of C++20 and a deeper look into modules
Overview of C++20 and a deeper look into modules
 
Intro to c++
Intro to c++Intro to c++
Intro to c++
 
Pwning in c++ (basic)
Pwning in c++ (basic)Pwning in c++ (basic)
Pwning in c++ (basic)
 
Modern C++
Modern C++Modern C++
Modern C++
 
C++ functions
C++ functionsC++ functions
C++ functions
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
 
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
 
JavaScript Robotics
JavaScript RoboticsJavaScript Robotics
JavaScript Robotics
 
Headache from using mathematical software
Headache from using mathematical softwareHeadache from using mathematical software
Headache from using mathematical software
 
C++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIAC++ functions presentation by DHEERAJ KATARIA
C++ functions presentation by DHEERAJ KATARIA
 
Learn c++ Programming Language
Learn c++ Programming LanguageLearn c++ Programming Language
Learn c++ Programming Language
 
C# What's next? (7.x and 8.0)
C# What's next? (7.x and 8.0)C# What's next? (7.x and 8.0)
C# What's next? (7.x and 8.0)
 
Антон Бикинеев, Reflection in C++Next
Антон Бикинеев,  Reflection in C++NextАнтон Бикинеев,  Reflection in C++Next
Антон Бикинеев, Reflection in C++Next
 
Auto cad 2006_api_overview
Auto cad 2006_api_overviewAuto cad 2006_api_overview
Auto cad 2006_api_overview
 
Connecting C++ and JavaScript on the Web with Embind
Connecting C++ and JavaScript on the Web with EmbindConnecting C++ and JavaScript on the Web with Embind
Connecting C++ and JavaScript on the Web with Embind
 
Rcpp
RcppRcpp
Rcpp
 
Programming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptxProgramming For Engineers Functions - Part #1.pptx
Programming For Engineers Functions - Part #1.pptx
 
Fp201 unit2 1
Fp201 unit2 1Fp201 unit2 1
Fp201 unit2 1
 
C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012 C++11 Idioms @ Silicon Valley Code Camp 2012
C++11 Idioms @ Silicon Valley Code Camp 2012
 

Dernier

Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmDeepika Walanjkar
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfChristianCDAM
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
 
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfPaper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfNainaShrivastava14
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdfCaalaaAbdulkerim
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communicationpanditadesh123
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfalene1
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsapna80328
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptJohnWilliam111370
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating SystemRashmi Bhat
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Erbil Polytechnic University
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingBootNeck1
 
CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfBalamuruganV28
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Coursebim.edu.pl
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodManicka Mamallan Andavar
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating SystemRashmi Bhat
 

Dernier (20)

Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdf
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
 
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdfPaper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
Paper Tube : Shigeru Ban projects and Case Study of Cardboard Cathedral .pdf
 
Research Methodology for Engineering pdf
Research Methodology for Engineering pdfResearch Methodology for Engineering pdf
Research Methodology for Engineering pdf
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communication
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveying
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.pptROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
ROBOETHICS-CCS345 ETHICS AND ARTIFICIAL INTELLIGENCE.ppt
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
Input Output Management in Operating System
Input Output Management in Operating SystemInput Output Management in Operating System
Input Output Management in Operating System
 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
 
System Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event SchedulingSystem Simulation and Modelling with types and Event Scheduling
System Simulation and Modelling with types and Event Scheduling
 
CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdf
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Course
 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument method
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating System
 

Writing good std::future&lt;c++>

  • 2. C++17 Standardization process. What we wanted and expected… • concepts • ranges • modules • parallel algorithms • .then on futures and other concurrency features • executors • coroutines with await • transactional memory • contracts • fold expressions • uniform function call syntax • constexpr lambdas • filesystem library • networking library • library features, e.g. any, optional, etc… • etc… Writing good std::future<C++>
  • 3. • concepts • ranges • modules • parallel algorithms • .then on futures and other concurrency features • executors • coroutines with await • transactional memory • contracts • fold expressions • uniform function call syntax • constexpr lambdas • filesystem library • networking library • library features, e.g. any, optional, etc… • etc… C++17 Standardization process. What we’ve got. Writing good std::future<C++>
  • 4. • concepts • ranges • modules • parallel algorithms • .then on futures and other concurrency features • executors • coroutines with await • transactional memory • contracts • fold expressions • uniform function call syntax • constexpr lambdas • filesystem library • networking library • library features, e.g. any, optional, etc… • etc… C++17 Standardization process. What we’ve got. Kenny Kerr @kennykerr 7 march C++11 attempted too much. C++14 fixed that. C++17 attempts too little. We need to fix that. Writing good std::future<C++>
  • 6. C++’s view on polymorphism Writing good std::future<C++>
  • 7. C++’s view on polymorphism class Factory { public: virtual AbstractButton* createButton() = 0; }; Writing good std::future<C++>
  • 8. C++’s view on polymorphism class Factory { public: virtual std::unique_ptr<AbstractButton> createButton() = 0; }; Writing good std::future<C++>
  • 9. C++’s view on polymorphism class Factory { public: virtual std::unique_ptr<AbstractButton> createButton() = 0; }; // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } Writing good std::future<C++>
  • 10. C++’s view on polymorphism // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } Writing good std::future<C++>
  • 11. C++’s view on polymorphism // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } Writing good std::future<C++>
  • 12. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself <members> Writing good std::future<C++> ConcreteFactory
  • 13. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself <members> movq %rsp, %rbp Writing good std::future<C++> ConcreteFactory
  • 14. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself <members> factory -24 movq %rdi, -24(%rbp) Writing good std::future<C++> ConcreteFactory
  • 15. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself <members> factory -24 movq -24(%rbp), %rax Writing good std::future<C++> ConcreteFactory
  • 16. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself factory -24 <members> vptr <ptrs to funs> &createButton Writing good std::future<C++> ConcreteFactory vtable
  • 17. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself factory -24 <members> vptr <ptrs to funs> &createButton movq (%rax), %rax Writing good std::future<C++> ConcreteFactory vtable
  • 18. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> the function itself factory -24 <members> vptr <ptrs to funs> &createButton addq $8, %rax Writing good std::future<C++> ConcreteFactory vtable
  • 19. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> <members> vptr <ptrs to funs> &createButton factory -24 the function itself movq (%rax), %rax Writing good std::future<C++> ConcreteFactory vtable
  • 20. Dynamic polymorphism rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> <members> vptr <ptrs to funs> &createButton factory -24 the function itselfcall %rax Writing good std::future<C++> ConcreteFactory vtable
  • 21. Dynamic polymorphism overhead rsp createForm frame rbp rdi rax x86_64 registers … <local vars, ra> ConcreteFactory <members> vptr vtable <ptrs to funs> &createButton factory -24 the function itself Writing good std::future<C++>
  • 22. C++ templates — solution? template <class Factory> void createForm(Factory& factory) { auto button = factory.createButton(); } Writing good std::future<C++>
  • 23. C++ templates — solution? template <class Factory> void createForm(Factory& factory) { auto button = factory.createButton(); } template void createForm(ConcreteFactory&); Writing good std::future<C++>
  • 24. C++ static interface. CRTP template <class Impl> struct Factory { std::unique_ptr<AbstractButton> createButton() { return static_cast<Impl*>(this)->createButton(); } }; Writing good std::future<C++>
  • 25. C++ static interface. CRTP template <class Impl> struct Factory { std::unique_ptr<AbstractButton> createButton() { return static_cast<Impl*>(this)->createButton(); } }; struct ConcreteFactory: Factory<ConcreteFactory> { std::unique_ptr<AbstractButton> createButton() { return std::make_unique<ConcreteButton>(); } }; Writing good std::future<C++>
  • 26. C++ static interface. Usage template <class Impl> void createForm(Factory<Impl>& fact) { auto button = fact.createButton(); } template void createForm(Factory<ConcreteFactory>&); Writing good std::future<C++>
  • 27. CRTP problems • looks like a hack; • no possibility to get nested types from Impl; • Impl is incomplete at point of instantiation. Writing good std::future<C++>
  • 28. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; Writing good std::future<C++>
  • 29. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; template <class T> requires factory<T> void createForm(T& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 30. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; template <factory T> void createForm(T& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 31. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; factory{T} void createForm(T& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 32. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; void createForm(factory& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 33. Defining concepts template <class T> concept bool variable_concept = constraint-expression; template <class T> concept bool function_concept() { return constraint-expression; } Writing good std::future<C++>
  • 34. Defining concepts. Type traits template <class T> concept bool integral = std::is_integral<T>::value; Writing good std::future<C++>
  • 35. Defining concepts. Type traits template <class T> concept bool integral = std::is_integral<T>()(); Writing good std::future<C++>
  • 36. Defining concepts. Type traits // from library fundamentals TS namespace std::experimental { template <class T> constexpr bool is_integral_v = is_integral<T>::value; } namespace stde = std::experimental; template <class T> concept bool integral = stde::is_integral_v<V>; Writing good std::future<C++>
  • 37. Concepts. Iterator example Writing good std::future<C++>
  • 38. Concepts. Iterator example template <class T> concept bool iterator = ...; Writing good std::future<C++>
  • 39. Concepts. Iterator example template <class T> concept bool swappable = requires (T t) { {std::swap(t, t)} -> void; } or requires (T t) { // for ADL {swap(t, t)} -> void; }; Writing good std::future<C++>
  • 40. Concepts. Iterator example template <class T> concept bool iterator = stde::is_copy_constructible_v<T> and stde::is_copy_assignable_v<T> and stde::is_destructible_v<T> and swappable<T> and requires (T r) { *r; {++r} -> T&; }; Writing good std::future<C++>
  • 41. Concepts. Input iterator template <class T> concept bool equality_comparable = requires (T t) { {t == t} -> bool; }; template <class T> concept bool input_iterator = iterator<T> and equality_comparable<T>; Writing good std::future<C++>
  • 42. Concepts. Forward iterator Writing good std::future<C++>
  • 43. Concepts. Forward iterator template <class T> concept bool forward_iterator = input_iterator<T> and stde::is_default_constructible_v<T> and requires (T r) { {r++} -> const T&; }; Writing good std::future<C++>
  • 44. Concepts. Bidirectional iterator template <class T> concept bool bidirectional_iterator = forward_iterator<T> and requires (T r) { {--r} -> T& {r--} -> const T&; }; Writing good std::future<C++>
  • 46. template <class T> concept bool random_access_iterator = bidirectional_iterator<T> and requires (T it, typename std::iterator_traits<T>::difference_type n) { {it += n} -> T&; {it + n} -> T; {n + it} -> T; {it -= n} -> T&; {it - it} -> typename std::iterator_traits<T>::difference_type; {it[n]} -> typename std::iterator_traits<T>::reference; {it < it} -> bool; {it <= it} -> bool; {it > it} -> bool; {it >= it} -> bool; }; Concepts. Random access iterator
  • 50. C++ generic programming and TMP Writing good std::future<C++>
  • 51. template <class _InputIterator> vector(_InputIterator __first, typename enable_if< __is_input_iterator<_InputIterator>::value && !__is_forward_iterator<_InputIterator>::value && is_constructible< value_type, typename iterator_traits< _InputIterator>::reference>::value, _InputIterator>::type __last); template <class _ForwardIterator> vector(_ForwardIterator __first, typename enable_if< __is_forward_iterator<_ForwardIterator>::value && is_constructible< value_type, typename iterator_traits< _ForwardIterator>::reference>::value, _ForwardIterator>::type __last); Without concepts: libc++ Writing good std::future<C++>
  • 52. vector(input_iterator __first, input_iterator __last); vector(forward_iterator __first, forward_iterator __last); With concepts: libc++ Writing good std::future<C++> That’s it!
  • 53. The greediness of T&& Writing good std::future<C++>
  • 54. // from Meyers’s EMC++ Item 26 std::multiset<std::string> names; void logAndAdd(const std::string& name) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(name); } The greediness of T&& Writing good std::future<C++>
  • 55. // from Meyers’s EMC++ Item 26 std::multiset<std::string> names; void logAndAdd(const std::string& name) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(name); } std::string petName("Darla"); logAndAdd(petName); // 1) logAndAdd(std::string("Persephone")); // 2) logAndAdd("Patty Dog”); // 3) The greediness of T&& Writing good std::future<C++>
  • 56. // from Meyers’s EMC++ Item 26 std::multiset<std::string> names; void logAndAdd(const std::string& name) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(name); } std::string petName("Darla"); logAndAdd(petName); // 1) okay, just copying logAndAdd(std::string("Persephone")); // 2) extra copy logAndAdd("Patty Dog”); // 3) no need to copy or move The greediness of T&& Writing good std::future<C++>
  • 57. The greediness of T&& // from Meyers’s EMC++ Item 26 template <typename T> void logAndAdd(T&& name) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(std::forward<T>(name)); } std::string petName("Darla"); logAndAdd(petName); // 1) okay, just copying logAndAdd(std::string("Persephone")); // 2) moving! logAndAdd("Patty Dog”); // 3) neither moving nor copying, // just creating inplaceWriting good std::future<C++>
  • 58. // from Meyers’s EMC++ Item 26 std::string nameFromIdx(int idx); void logAndAdd(int idx) { auto now = std::chrono::system_clock::now(); log(now, "logAndAdd"); names.emplace(nameFromIdx(idx)); } short nameIdx; logAndAdd(nameIdx); // error! The greediness of T&& Writing good std::future<C++>
  • 59. Meyers, “Effective Modern C++”, Item 26: Avoid overloading on universal references. The greediness of T&& Writing good std::future<C++>
  • 60. Meyers, “Effective Modern C++”, Item 26: Avoid overloading on universal references. ... The greediness of T&& Writing good std::future<C++>
  • 61. Meyers, “Effective Modern C++”, Item 26: Avoid overloading on universal references. ... but not on constrained universal references! The greediness of T&& Writing good std::future<C++>
  • 62. void logAndAdd(int idx); template <typename T> void logAndAdd(T&& name) { ... names.emplace(std::forward<T>(name)); } Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 63. void logAndAdd(int idx); template <typename T, typename = std::enable_if_t< stde::is_convertible_v< T, std::string>>> void logAndAdd(T&& name) { ... names.emplace(std::forward<T>(name)); } Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 64. void logAndAdd(int idx); template <typename T, typename = std::enable_if_t< stde::is_convertible_v< std::remove_reference_t<T>, std::string>>> void logAndAdd(T&& name) { ... names.emplace(std::forward<T>(name)); } Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 65. void logAndAdd(int idx); template <typename T, typename = std::enable_if_t< stde::is_convertible_v< std::remove_reference_t<T>, std::string>>> void logAndAdd(T&& name) { ... names.emplace(std::forward<T>(name)); } short nameIdx; logAndAdd(nameIdx); // calls logAndAdd(int) just fine! Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 66. template <class From, class To> concept bool convertible = stde::is_convertible_v< std::remove_reference_t<From>, To>; Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 67. template <class From, class To> concept bool convertible = stde::is_convertible_v< std::remove_reference_t<From>, To>; void logAndAdd(convertible<std::string>&& name) { ... names.emplace(std::forward<decltype(name)>(name)); } short nameIdx; logAndAdd(nameIdx); // calls logAndAdd(int) just fine! Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 68. // from Meyers’s EMC++ Item 26 class Person { public: template <typename T> explicit Person(T&& n) // perfect forwarding ctor : name(std::forward<T>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {} private: std::string name; }; Constrained T&& as the best parameter type for efficiency and safety Writing good std::future<C++>
  • 69. // from Meyers’s EMC++ Item 26 class Person { public: template <typename T> explicit Person(T&& n) // perfect forwarding ctor : name(std::forward<T>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {} private: std::string name; }; Person p("Nancy"); auto cloneOfP(p); // WOW! Constrained T&& as the best parameter type for efficiency and safety
  • 70. // from Meyers’s EMC++ Item 26 class Person { public: explicit Person(convertible<std::string>&& n) : name(std::forward<decltype(n)>(n)) {} explicit Person(int idx) : name(nameFromIdx(idx)) {} private: std::string name; }; Person p("Nancy"); auto cloneOfP(p); // now works fine! Constrained T&& as the best parameter type for efficiency and safety
  • 72. namespace boost::container { template <class Key, class Value, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<Key, Value>>> class flat_map; } C++17 example: boost::flat_map Writing good std::future<C++>
  • 73. namespace mine::container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, Value>>> class flat_map; } C++17 example: my flat_map Writing good std::future<C++>
  • 74. namespace mine::container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, Value>>> requires default_constructible<Value> class flat_map; } C++17 example: my flat_map Writing good std::future<C++>
  • 75. namespace mine::container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, Value>>> requires default_constructible<Value> and random_access_iterator< typename UnderlyingContainer::iterator> class flat_map; } C++17 example: my flat_map Writing good std::future<C++>
  • 76. namespace mine::container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, Value>>> requires default_constructible<Value> and random_access_iterator< typename UnderlyingContainer::iterator> and requires (Compare cmp, Key key) { {cmp(key, key)} -> bool; } class flat_map; } C++17 example: my flat_map Writing good std::future<C++>
  • 77. template <...> class flat_map final: private UnderlyingContainer { using key_type = Key; using mapped_type = Value; using underlying_type = UnderlyingContainer; using typename underlying_type::value_type; static_assert(stde::is_same_v<value_type, std::pair<key_type, mapped_type>>); using key_compare = Compare; using value_compare = struct { ... }; }; flat_map: typedefs Writing good std::future<C++>
  • 78. template <...> class flat_map final: private UnderlyingContainer { using value_compare = struct { bool operator()(const value_type& left, const value_type& right) const { return key_compare()(left.first, right.first); } bool operator()(const key_type& left, const value_type& right) const { return key_compare()(left, right.first); } bool operator()(const value_type& left, const key_type& right) const { return key_compare()(left.first, right); }}; }; flat_map: typedefs Writing good std::future<C++>
  • 79. template <...> class flat_map final: private UnderlyingContainer { using typename underlying_type::size_type; using typename underlying_type::difference_type; using typename underlying_type::allocator_type; using typename underlying_type::reference; using typename underlying_type::const_reference; using typename underlying_type::pointer; using typename underlying_type::const_pointer; using typename underlying_type::iterator; using typename underlying_type::const_iterator; using typename underlying_type::reverse_iterator; using typename underlying_type::const_reverse_iterator; }; flat_map: typedefs Writing good std::future<C++>
  • 80. template <...> class flat_map final: private UnderlyingContainer { using underlying_type::begin; // laconic wrapping using underlying_type::cbegin; using underlying_type::end; using underlying_type::cend; using underlying_type::rbegin; using underlying_type::crbegin; using underlying_type::rend; using underlying_type::crend; }; flat_map: laconic wrapping Writing good std::future<C++>
  • 81. template <...> class flat_map final: private UnderlyingContainer { using underlying_type::swap; using underlying_type::clear; using underlying_type::empty; using underlying_type::size; using underlying_type::max_size; using underlying_type::capacity; using underlying_type::reserve; using underlying_type::shrink_to_fit; }; flat_map: laconic wrapping Writing good std::future<C++>
  • 82. template <...> class flat_map final: private UnderlyingContainer { flat_map() = default; template <class Iterator> flat_map(Iterator first, Iterator last): underlying_type{first, last} { std::sort(begin(), end()); } flat_map(std::initializer_list<value_type> list): flat_map{list.begin(), list.end()} { } }; flat_map: ctors Writing good std::future<C++>
  • 83. template <...> class flat_map final: private UnderlyingContainer { flat_map() = default; flat_map(input_iterator first, input_iterator last): underlying_type{first, last} { std::sort(begin(), end()); } flat_map(std::initializer_list<value_type> list): flat_map{list.begin(), list.end()} { } }; flat_map: ctors Writing good std::future<C++>
  • 84. template <...> class flat_map final: private UnderlyingContainer { flat_map() = default; flat_map(input_iterator first, input_iterator last): underlying_type{first, last} { stde::sort(stde::par, begin(), end()); } flat_map(std::initializer_list<value_type> list): flat_map{list.begin(), list.end()} { } }; flat_map: ctors Writing good std::future<C++>
  • 85. namespace detail { template <class Iterator, class Key, class Compare> Iterator binary_search(Iterator begin, Iterator end, const Key& key, const Compare& cmp) { auto it = std::lower_bound(begin, end, key, cmp); if (it == end || cmp(key, *it)) return end; return it; } } flat_map: binary_search Writing good std::future<C++>
  • 86. namespace detail { auto binary_search(forward_iterator begin, forward_iterator end, const auto& key, const auto& cmp) { auto it = std::lower_bound(begin, end, key, cmp); if (it == end || cmp(key, *it)) return end; return it; } } flat_map: binary_search Writing good std::future<C++>
  • 87. template <...> class flat_map final: private UnderlyingContainer { iterator find(const key_type& key) { return detail::binary_search( begin(), end(), key, value_compare{}); } const_iterator find(const key_type& key) const { return detail::binary_search( cbegin(), cend(), key, value_compare{}); } }; flat_map: find Writing good std::future<C++>
  • 88. template <...> class flat_map final: private UnderlyingContainer { mapped_type& at(const key_type& key) { const auto it = find(key); if (it == end()) throw std::range_error(“no key”); return it->second; } const mapped_type& at(const key_type& key) const { // same as above } }; flat_map: at Writing good std::future<C++>
  • 89. template <...> class flat_map final: private UnderlyingContainer { std::pair<iterator, bool> emplace( auto&& first, auto&&... args) { value_compare comp; const auto it = std::lower_bound( begin(), end(), first, comp); if (it == end() || comp(first, *it)) return {underlying_type::emplace(it, std::forward<decltype(first)>(first), std::forward<decltype(args)>(args)...), true}; return {it, false}; } }; flat_map: emplace Writing good std::future<C++>
  • 90. template <...> class flat_map final: private UnderlyingContainer { std::pair<iterator, bool> insert(const value_type& value) { return emplace(value); } }; flat_map: insert Writing good std::future<C++>
  • 91. template <...> class flat_map final: private UnderlyingContainer { std::pair<iterator, bool> insert(const value_type& value) { return emplace(value); } std::pair<iterator, bool> insert(value_type&& value) { return emplace(std::move(value)); } }; flat_map: insert Writing good std::future<C++>
  • 92. template <...> class flat_map final: private UnderlyingContainer { std::pair<iterator, bool> insert( convertible<value_type>&& value) { return emplace(std::forward<decltype(value)>(value)); } // no need to provide anything else! }; flat_map: insert Writing good std::future<C++>
  • 93. template <...> class flat_map final: private UnderlyingContainer { void insert(input_iterator first, input_iterator last) { const auto count = std::distance(first, last); const auto room = capacity() - size(); if (room < count) reserve(size() + count); for (; first != last; ++first) emplace(*first); } }; flat_map: insert Writing good std::future<C++>
  • 94. template <...> class flat_map final: private UnderlyingContainer { void insert(std::initializer_list<value_type> list) { insert(list.begin(), list.end()); } }; flat_map: insert Writing good std::future<C++>
  • 95. template <...> class flat_map final: private UnderlyingContainer { mapped_type& operator[](convertible<key_type>&& key) { return emplace( std::forward<decltype(key)>(key), mapped_type{} ).first->second; } }; flat_map: index operator Writing good std::future<C++>
  • 96. template <...> class flat_map final: private UnderlyingContainer { using underlying_type::erase; size_type erase(const key_type& key) { const auto it = find(key); if (it == end()) return 0u; erase(it); return 1u; } }; flat_map: erase Writing good std::future<C++>
  • 97. Modularizing flat_map. Interface Writing good std::future<C++> // flat_map.hpp #include <...> namespace container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, T>>> class flat_map { ... }; }
  • 98. Modularizing flat_map. Interface Writing good std::future<C++> // flat_map.ixx #include <...> module container.flat_map; export namespace container { template <class Key, class Value, class Compare = std::less<Key>, class UnderlyingContainer = std::vector<std::pair<Key, T>>> class flat_map { ... }; }
  • 99. Modularizing flat_map. Consuming Writing good std::future<C++> // main.cpp import std.io; import container.flat_map; int main() { container::flat_map<std::string, int> map = {{"second", 2}, {"first", 1}, {"third", 3}}; for (const auto& p: map) std::cout << p.first << ": " << p.second << std::endl; return 0; }
  • 100. Some more slides… Writing good std::future<C++>
  • 101. Static polymorphism with concepts. Improving template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; void createForm(factory& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 102. Static polymorphism with concepts. Improving struct AbstractButton { virtual void onClick(std::function<void ()>) = 0; virtual void onMove (std::function<void ()>) = 0; }; Writing good std::future<C++>
  • 103. Static polymorphism with concepts. Improving namespace detail // or std? or whatever { constexpr auto empty = [](auto...){}; } template <class T> concept bool button = requires (T t) { t.onClick(detail::empty); t.onMove(detail::empty); }; Writing good std::future<C++>
  • 104. Static polymorphism with concepts. Improving template <class T> concept bool button = ...; template <class T> concept bool factory = requires (T t) { {t.createButton()} -> button; }; Writing good std::future<C++>
  • 105. Static polymorphism with concepts. Improving class TButton { void onClick(...); void onMove(...); }; class QPushButton { void onClick(...); void onMove(...); }; Writing good std::future<C++>
  • 106. Static polymorphism with concepts. Improving class TButton { void onClick(...); void onMove(...); }; class QPushButton { void onClick(...); void onMove(...); }; class VCLFactory { TButton createButton() { return TButton{}; } }; class QtFactory { QPushButton createButton() { return QPushButton{}; } }; Writing good std::future<C++>
  • 107. Static polymorphism with concepts. Using void createForm(factory& fact) { auto button = fact.createButton(); button.onClick([]{ /* pum pum pum */ }); } int main() { QtFactory factory; createForm(factory); QApplication::run(); } Writing good std::future<C++>
  • 108. Writing good std::future<C++> Thank you for your attention!