SlideShare a Scribd company logo
1 of 102
Download to read offline
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++>
Dynamic polymorphism
class Factory
{
public:
virtual AbstractButton* createButton() = 0;
};
Writing good std::future<C++>
Dynamic polymorphism
class Factory
{
public:
virtual std::unique_ptr<AbstractButton> createButton() = 0;
};
Writing good std::future<C++>
Dynamic 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++>
Dynamic polymorphism
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
Writing good std::future<C++>
Dynamic polymorphism
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
$clang++-4.0 -O3 -S test.cc -o -
Writing good std::future<C++>
Dynamic polymorphism: overhead
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
$clang++-4.0 -O3 -S test.cc -o -
Writing good std::future<C++>
Dynamic polymorphism: overhead
// use of polymorphic code
void createForm(Factory* factory)
{
auto button = factory->createButton();
}
$clang++-4.0 -O3 -S test.cc -o -
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&);
$clang++-4.0 -O3 -S test.cc -o -
Writing good std::future<C++>
C++ templates — solution?
template <class Factory>
void createForm(Factory& factory)
{
auto button = factory.createButton();
}
template void createForm(ConcreteFactory&);
$clang++-4.0 -O3 -S test.cc -o -
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();
}
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>&);
$clang++-4.0 -O3 -S test.cc -o -
Writing good std::future<C++>
CRTP problems
• looks like a hack;
• no possibility to get nested types from Impl;
• Impl is incomplete at its 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
// variable concept
template <class T>
concept bool variable_concept = constraint-expression;
// function concept
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
Writing good std::future<C++>
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
Writing good std::future<C++>
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++
That’s it!
Writing good std::future<C++>
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) extra creation and copying
The greediness of T&&
actually, no need!
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 in-place
Writing 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
Writing good std::future<C++>
// 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
Writing good std::future<C++>
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
// 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
{
...
};
}
Writing good std::future<C++>
Modularizing flat_map. Interface
// 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
{
...
};
}
Writing good std::future<C++>
Modularizing flat_map. Consuming
// 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;
}
Writing good std::future<C++>
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++>
Thank you for your attention!
Writing good std::future<C++>

More Related Content

What's hot

Дмитрий Демчук. Кроссплатформенный краш-репорт
Дмитрий Демчук. Кроссплатформенный краш-репортДмитрий Демчук. Кроссплатформенный краш-репорт
Дмитрий Демчук. Кроссплатформенный краш-репортSergey Platonov
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumlercorehard_by
 
Алексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляАлексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляSergey Platonov
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Sergey Platonov
 
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
 
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
Gor Nishanov,  C++ Coroutines – a negative overhead abstractionGor Nishanov,  C++ Coroutines – a negative overhead abstraction
Gor Nishanov, C++ Coroutines – a negative overhead abstractionSergey Platonov
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done rightPlatonov Sergey
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Mr. Vengineer
 
Welcome to Modern C++
Welcome to Modern C++Welcome to Modern C++
Welcome to Modern C++Seok-joon Yun
 
Basic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersBasic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersAppier
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptSeok-joon Yun
 
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
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and deletePlatonov Sergey
 
C++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingC++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingcppfrug
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckAndrey Karpov
 
Коварный code type ITGM #9
Коварный code type ITGM #9Коварный code type ITGM #9
Коварный code type ITGM #9Andrey Zakharevich
 

What's hot (20)

Дмитрий Демчук. Кроссплатформенный краш-репорт
Дмитрий Демчук. Кроссплатформенный краш-репортДмитрий Демчук. Кроссплатформенный краш-репорт
Дмитрий Демчук. Кроссплатформенный краш-репорт
 
C++20 the small things - Timur Doumler
C++20 the small things - Timur DoumlerC++20 the small things - Timur Doumler
C++20 the small things - Timur Doumler
 
Joel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMDJoel Falcou, Boost.SIMD
Joel Falcou, Boost.SIMD
 
Алексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуляАлексей Кутумов, Вектор с нуля
Алексей Кутумов, Вектор с нуля
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
Александр Гранин, Функциональная 'Жизнь': параллельные клеточные автоматы и к...
 
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
 
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
Gor Nishanov,  C++ Coroutines – a negative overhead abstractionGor Nishanov,  C++ Coroutines – a negative overhead abstraction
Gor Nishanov, C++ Coroutines – a negative overhead abstraction
 
C++ references
C++ referencesC++ references
C++ references
 
Multithreading done right
Multithreading done rightMultithreading done right
Multithreading done right
 
Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。Tiramisu をちょっと、味見してみました。
Tiramisu をちょっと、味見してみました。
 
Welcome to Modern C++
Welcome to Modern C++Welcome to Modern C++
Welcome to Modern C++
 
Basic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python ProgrammersBasic C++ 11/14 for Python Programmers
Basic C++ 11/14 for Python Programmers
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScript
 
Vocabulary Types in C++17
Vocabulary Types in C++17Vocabulary Types in C++17
Vocabulary Types in C++17
 
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
 
С++ without new and delete
С++ without new and deleteС++ without new and delete
С++ without new and delete
 
C++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogrammingC++ How I learned to stop worrying and love metaprogramming
C++ How I learned to stop worrying and love metaprogramming
 
Picking Mushrooms after Cppcheck
Picking Mushrooms after CppcheckPicking Mushrooms after Cppcheck
Picking Mushrooms after Cppcheck
 
Коварный code type ITGM #9
Коварный code type ITGM #9Коварный code type ITGM #9
Коварный code type ITGM #9
 

Viewers also liked

Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыPlatonov Sergey
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерSergey Platonov
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиvictor-yastrebov
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castRoman Orlov
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3Platonov Sergey
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеIlia Shishkov
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines Sergey Zubkov
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projectscorehard_by
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit TestingDmitry Vyukov
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Mikhail Matrosov
 
Василий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейВасилий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейSergey Platonov
 

Viewers also liked (17)

Григорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизацияГригорий Демченко, Асинхронность и неблокирующая синхронизация
Григорий Демченко, Асинхронность и неблокирующая синхронизация
 
Конкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнерыКонкурентные ассоциативные контейнеры
Конкурентные ассоциативные контейнеры
 
Григорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптерГригорий Демченко, Универсальный адаптер
Григорий Демченко, Универсальный адаптер
 
Использование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработкиИспользование юнит-тестов для повышения качества разработки
Использование юнит-тестов для повышения качества разработки
 
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptСергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
 
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
 
Parallel STL
Parallel STLParallel STL
Parallel STL
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловПолухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
 
Догнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_castДогнать и перегнать boost::lexical_cast
Догнать и перегнать boost::lexical_cast
 
Алексей Кутумов, C++ без исключений, часть 3
Алексей Кутумов,  C++ без исключений, часть 3Алексей Кутумов,  C++ без исключений, часть 3
Алексей Кутумов, C++ без исключений, часть 3
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Фитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в формеФитнес для вашего кода: как держать его в форме
Фитнес для вашего кода: как держать его в форме
 
C++ Core Guidelines
C++ Core Guidelines C++ Core Guidelines
C++ Core Guidelines
 
Quality assurance of large c++ projects
Quality assurance of large c++ projectsQuality assurance of large c++ projects
Quality assurance of large c++ projects
 
Fuzzing: The New Unit Testing
Fuzzing: The New Unit TestingFuzzing: The New Unit Testing
Fuzzing: The New Unit Testing
 
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
Повседневный С++: алгоритмы и итераторы @ C++ Russia 2017
 
Василий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексиейВасилий Сорокин, Простой REST сервер на Qt с рефлексией
Василий Сорокин, Простой REST сервер на Qt с рефлексией
 

Similar to Антон Бикинеев, 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++>corehard_by
 
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
 
Milot Shala - C++ (OSCAL2014)
Milot Shala - C++ (OSCAL2014)Milot Shala - C++ (OSCAL2014)
Milot Shala - C++ (OSCAL2014)Open Labs Albania
 
Introduction to C#
Introduction to C#Introduction to C#
Introduction to C#ANURAG SINGH
 
Design Patterns in Modern C++
Design Patterns in Modern C++Design Patterns in Modern C++
Design Patterns in Modern C++Dmitri Nesteruk
 
TEMPLATES IN JAVA
TEMPLATES IN JAVATEMPLATES IN JAVA
TEMPLATES IN JAVAMuskanSony
 
Types, classes and concepts
Types, classes and conceptsTypes, classes and concepts
Types, classes and conceptsNicola Bonelli
 
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеДмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеSergey Platonov
 
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
 
Cpp17 and Beyond
Cpp17 and BeyondCpp17 and Beyond
Cpp17 and BeyondComicSansMS
 
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksBeginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksJinTaek Seo
 

Similar to Антон Бикинеев, 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++>
 
report
reportreport
report
 
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
 
2CPP15 - Templates
2CPP15 - Templates2CPP15 - Templates
2CPP15 - Templates
 
Milot Shala - C++ (OSCAL2014)
Milot Shala - C++ (OSCAL2014)Milot Shala - C++ (OSCAL2014)
Milot Shala - C++ (OSCAL2014)
 
Beyond C++17
Beyond C++17Beyond C++17
Beyond C++17
 
Intro to c++
Intro to c++Intro to c++
Intro to c++
 
Introduction to C#
Introduction to C#Introduction to C#
Introduction to C#
 
Design Patterns in Modern C++
Design Patterns in Modern C++Design Patterns in Modern C++
Design Patterns in Modern C++
 
Modern C++
Modern C++Modern C++
Modern C++
 
TEMPLATES IN JAVA
TEMPLATES IN JAVATEMPLATES IN JAVA
TEMPLATES IN JAVA
 
Types, classes and concepts
Types, classes and conceptsTypes, classes and concepts
Types, classes and concepts
 
Дмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI векеДмитрий Нестерук, Паттерны проектирования в XXI веке
Дмитрий Нестерук, Паттерны проектирования в XXI веке
 
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)
 
Cpp17 and Beyond
Cpp17 and BeyondCpp17 and Beyond
Cpp17 and Beyond
 
C_plus_plus
C_plus_plusC_plus_plus
C_plus_plus
 
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeksBeginning direct3d gameprogrammingcpp02_20160324_jintaeks
Beginning direct3d gameprogrammingcpp02_20160324_jintaeks
 
Return of c++
Return of c++Return of c++
Return of c++
 
Templates2
Templates2Templates2
Templates2
 
C#unit4
C#unit4C#unit4
C#unit4
 

More from Sergey Platonov

Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаЛев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаSergey Platonov
 
Павел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.ioПавел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.ioSergey Platonov
 
Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17Sergey Platonov
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Sergey Platonov
 
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtДенис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtSergey Platonov
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковSergey Platonov
 
Dori Exterman, Considerations for choosing the parallel computing strategy th...
Dori Exterman, Considerations for choosing the parallel computing strategy th...Dori Exterman, Considerations for choosing the parallel computing strategy th...
Dori Exterman, Considerations for choosing the parallel computing strategy th...Sergey Platonov
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Sergey Platonov
 
Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Sergey Platonov
 
Михаил Матросов, Повседневный С++: boost и STL
Михаил Матросов, Повседневный С++: boost и STLМихаил Матросов, Повседневный С++: boost и STL
Михаил Матросов, Повседневный С++: boost и STLSergey Platonov
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Илья Шишков, Принципы создания тестируемого кода
Илья Шишков, Принципы создания тестируемого кодаИлья Шишков, Принципы создания тестируемого кода
Илья Шишков, Принципы создания тестируемого кодаSergey Platonov
 
Антон Наумович, Система автоматической крэш-аналитики своими средствами
Антон Наумович, Система автоматической крэш-аналитики своими средствамиАнтон Наумович, Система автоматической крэш-аналитики своими средствами
Антон Наумович, Система автоматической крэш-аналитики своими средствамиSergey Platonov
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаSergey Platonov
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
 

More from Sergey Platonov (17)

Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного багаЛев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
Лев Казаркин, Удивительные приключения регистров SSE или в поисках одного бага
 
Павел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.ioПавел Филонов, Разделяй и управляй вместе с Conan.io
Павел Филонов, Разделяй и управляй вместе с Conan.io
 
Антон Полухин. C++17
Антон Полухин. C++17Антон Полухин. C++17
Антон Полухин. C++17
 
Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++Павел Беликов, Как избежать ошибок, используя современный C++
Павел Беликов, Как избежать ошибок, используя современный C++
 
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на QtДенис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
Денис Кандров, Пушкова Евгения, QSpec: тестирование графических приложений на Qt
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворковНикита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
 
Dori Exterman, Considerations for choosing the parallel computing strategy th...
Dori Exterman, Considerations for choosing the parallel computing strategy th...Dori Exterman, Considerations for choosing the parallel computing strategy th...
Dori Exterman, Considerations for choosing the parallel computing strategy th...
 
Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++Александр Фокин, Рефлексия в C++
Александр Фокин, Рефлексия в C++
 
Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++Антон Нонко, Классические строки в C++
Антон Нонко, Классические строки в C++
 
Михаил Матросов, Повседневный С++: boost и STL
Михаил Матросов, Повседневный С++: boost и STLМихаил Матросов, Повседневный С++: boost и STL
Михаил Матросов, Повседневный С++: boost и STL
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
Илья Шишков, Принципы создания тестируемого кода
Илья Шишков, Принципы создания тестируемого кодаИлья Шишков, Принципы создания тестируемого кода
Илья Шишков, Принципы создания тестируемого кода
 
Антон Наумович, Система автоматической крэш-аналитики своими средствами
Антон Наумович, Система автоматической крэш-аналитики своими средствамиАнтон Наумович, Система автоматической крэш-аналитики своими средствами
Антон Наумович, Система автоматической крэш-аналитики своими средствами
 
Андрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кодаАндрей Карпов, Приватные байки от разработчиков анализатора кода
Андрей Карпов, Приватные байки от разработчиков анализатора кода
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
 

Recently uploaded

%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastPapp Krisztián
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...masabamasaba
 

Recently uploaded (20)

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 

Антон Бикинеев, 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. Dynamic polymorphism class Factory { public: virtual AbstractButton* createButton() = 0; }; Writing good std::future<C++>
  • 8. Dynamic polymorphism class Factory { public: virtual std::unique_ptr<AbstractButton> createButton() = 0; }; Writing good std::future<C++>
  • 9. Dynamic 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. Dynamic polymorphism // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } Writing good std::future<C++>
  • 11. Dynamic polymorphism // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 12. Dynamic polymorphism: overhead // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 13. Dynamic polymorphism: overhead // use of polymorphic code void createForm(Factory* factory) { auto button = factory->createButton(); } $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 14. C++ templates — solution? template <class Factory> void createForm(Factory& factory) { auto button = factory.createButton(); } Writing good std::future<C++>
  • 15. C++ templates — solution? template <class Factory> void createForm(Factory& factory) { auto button = factory.createButton(); } template void createForm(ConcreteFactory&); $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 16. C++ templates — solution? template <class Factory> void createForm(Factory& factory) { auto button = factory.createButton(); } template void createForm(ConcreteFactory&); $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 17. 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++>
  • 18. 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++>
  • 19. C++ static interface. Usage template <class Impl> void createForm(Factory<Impl>& fact) { auto button = fact.createButton(); } Writing good std::future<C++>
  • 20. C++ static interface. Usage template <class Impl> void createForm(Factory<Impl>& fact) { auto button = fact.createButton(); } template void createForm(Factory<ConcreteFactory>&); $clang++-4.0 -O3 -S test.cc -o - Writing good std::future<C++>
  • 21. CRTP problems • looks like a hack; • no possibility to get nested types from Impl; • Impl is incomplete at its point of instantiation. Writing good std::future<C++>
  • 22. Concepts — solution? template <class T> concept bool factory = requires (T t) { {t.createButton()} -> std::unique_ptr<AbstractButton>; }; Writing good std::future<C++>
  • 23. 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++>
  • 24. 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++>
  • 25. 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++>
  • 26. 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++>
  • 27. Defining concepts // variable concept template <class T> concept bool variable_concept = constraint-expression; // function concept template <class T> concept bool function_concept() { return constraint-expression; } Writing good std::future<C++>
  • 28. Defining concepts. Type traits template <class T> concept bool integral = std::is_integral<T>::value; Writing good std::future<C++>
  • 29. Defining concepts. Type traits template <class T> concept bool integral = std::is_integral<T>()(); Writing good std::future<C++>
  • 30. 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++>
  • 31. Concepts. Iterator example Writing good std::future<C++>
  • 32. Concepts. Iterator example template <class T> concept bool iterator = ...; Writing good std::future<C++>
  • 33. 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++>
  • 34. 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++>
  • 35. 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++>
  • 36. Concepts. Forward iterator Writing good std::future<C++>
  • 37. 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++>
  • 38. 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++>
  • 39. Concepts. Random access iterator Writing good std::future<C++>
  • 40. 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 Writing good std::future<C++>
  • 44. C++ generic programming and TMP Writing good std::future<C++>
  • 45. 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++>
  • 46. vector(input_iterator __first, input_iterator __last); vector(forward_iterator __first, forward_iterator __last); With concepts: libc++ That’s it! Writing good std::future<C++>
  • 47. The greediness of T&& Writing good std::future<C++>
  • 48. // 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++>
  • 49. // 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++>
  • 50. // 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) extra creation and copying The greediness of T&& actually, no need! Writing good std::future<C++>
  • 51. 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 in-place Writing good std::future<C++>
  • 52. // 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++>
  • 53. Meyers, “Effective Modern C++”, Item 26: Avoid overloading on universal references. The greediness of T&& Writing good std::future<C++>
  • 54. Meyers, “Effective Modern C++”, Item 26: Avoid overloading on universal references. ... The greediness of T&& Writing good std::future<C++>
  • 55. 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++>
  • 56. 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++>
  • 57. 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++>
  • 58. 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++>
  • 59. 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++>
  • 60. 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++>
  • 61. 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++>
  • 62. // 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++>
  • 63. // 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 Writing good std::future<C++>
  • 64. // 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 Writing good std::future<C++>
  • 66. 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++>
  • 67. 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++>
  • 68. 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++>
  • 69. 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++>
  • 70. 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++>
  • 71. 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++>
  • 72. 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++>
  • 73. 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++>
  • 74. 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++>
  • 75. 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++>
  • 76. 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++>
  • 77. 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++>
  • 78. 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++>
  • 79. 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++>
  • 80. 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++>
  • 81. 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++>
  • 82. 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++>
  • 83. 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++>
  • 84. 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++>
  • 85. 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++>
  • 86. 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++>
  • 87. 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++>
  • 88. 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++>
  • 89. 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++>
  • 90. 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++>
  • 91. Modularizing flat_map. Interface // 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 { ... }; } Writing good std::future<C++>
  • 92. Modularizing flat_map. Interface // 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 { ... }; } Writing good std::future<C++>
  • 93. Modularizing flat_map. Consuming // 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; } Writing good std::future<C++>
  • 94. Some more slides… Writing good std::future<C++>
  • 95. 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++>
  • 96. 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++>
  • 97. 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++>
  • 98. 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++>
  • 99. Static polymorphism with concepts. Improving class TButton { void onClick(...); void onMove(...); }; class QPushButton { void onClick(...); void onMove(...); }; Writing good std::future<C++>
  • 100. 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++>
  • 101. 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++>
  • 102. Thank you for your attention! Writing good std::future<C++>