Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Алексей Кутумов, C++ без исключений, часть 3

5,954 views

Published on

В своих прошлых докладах (http://cpp-russia.ru/?p=198, и http://cpp-russia.ru/?page_id=1239) я рассказывал о C++ без исключений, как с эти жить, как работать. Этот доклад является продолжением этой серии. Я рекомендую освежить в памяти предыдущие доклады, чтобы наша работа была более продуктивной. Мы обсудим механизмы создания, копирования и перемещения объектов, механизмы аллокации и деаллокации памяти, а также обработку ошибок и исключений. Также мы обсудим проблемы и неудобства, которые испытывает программист, когда пишет код без исключений. В конце, я попытаюсь показать, как можно проектировать структуры данных, контейнеры для удобной работы в средах с исключениями и без исключений.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Алексей Кутумов, C++ без исключений, часть 3

  1. 1. C++ WITHOUT EXCEPTIONS, PART 3 Alexey Kutumov Senior software engineer at Kaspersky Lab
  2. 2. AGENDA Зачем нужен C++ без исключений Ограничения и проблемы Решение проблем … Profit!
  3. 3. ЗАЧЕМ НУЖЕН C++ БЕЗ ИСКЛЮЧЕНИЙ
  4. 4. C++ БЕЗ ИСКЛЮЧЕНИЙ try { throw std::logic_error(""); } catch (...) { // handle error } error C2980: C++ exception handling is not supported with /kernel
  5. 5. C++ БЕЗ ИСКЛЮЧЕНИЙ System programming Game development High-performance software (trading systems)
  6. 6. ОГРАНИЧЕНИЯ
  7. 7. ОГРАНИЧЕНИЯ std::string message{"This string should be long enough..."};
  8. 8. ОГРАНИЧЕНИЯ std::error_condition ec; nestl::string message{"This string should be long enough...", ec}; if (ec) { // handle error }
  9. 9. ОГРАНИЧЕНИЯ std::error_condition ec; nestl::string message{"This string should be long enough...", ec}; if (ec) { // handle error } nestl::string message2; message2 = message;
  10. 10. ОГРАНИЧЕНИЯ std::error_condition ec; nestl::string message{"This string should be long enough...", ec}; if (ec) { // handle error } nestl::string message2; message2.assign_copy(message, ec);
  11. 11. ОГРАНИЧЕНИЯ Есть исключения Нет исключений Операция кидает исключение Операция возвращает ошибку Конструктор копирования Двухфазная инициализация Оператор присваивания Явный метод копирования
  12. 12. ПРОБЛЕМЫ
  13. 13. ПРОБЛЕМЫ С++ без исключений вынуждает программиста ослаблять инварианты класса
  14. 14. ПРОБЛЕМЫ struct MyClass { explicit MyClass(std::unique_ptr<Connection>&& connection) { if (!connection) { throw std::logic_error("connection is empty"); } m_connection = std::move(connection); } std::unique_ptr<Connection> m_connection; };
  15. 15. ПРОБЛЕМЫ С++ без исключений вынуждает программиста писать больше кода
  16. 16. ПРОБЛЕМЫ #define TRY(expr) expr; if (ec) {return;} // without exceptions TRY(msg2.assign_copy(msg, ec)); TRY(Foo(msg, ec)); TRY(Bar(msg2, ec)); TRY(Baz(42, ec)); // with exceptions msg2 = msg; Foo(msg); Bar(msg2); Baz(42);
  17. 17. ПРОБЛЕМЫ struct Message { nestl::string id; nestl::vector<int> data; void assign_copy(const Message& other, std::error_condition& ec) { TRY(id.assign_copy(other.id, ec)); TRY(data.assign_copy(other.data, ec)); } };
  18. 18. FUTURE compile-time reflection magic_get (C++-14/C++-17) от Антона Полухина
  19. 19. CURRENT noexcept (part of function type since C++-17) std::move std::is_nothrow_constructible (default, copy, move) std::is_nothrow_assignable (copy, move) std::is_nothrow_swappable (since C++-17)
  20. 20. NOEXCEPT PROPAGATION struct SimpleData { SimpleData() noexcept : x(42) {} int x; }; struct CompositeData { SimpleData d; float f; }; static_assert(std::is_nothrow_default_constructible_v<SimpleData>, ""); static_assert(std::is_nothrow_default_constructible_v<CompositeData>, "");
  21. 21. ДЛЯ ЧЕГО НУЖНЫ TYPE_TRAITS nestl::vector<Message> msgList; nestl::vector<CompositeData> dataList; Message msg = get_message(); CompositeData data = get_data(); std::error_condition ec; TRY(msgList.push_back_nothrow(msg, ec)); TRY(dataList.push_back_nothrow(data, ec));
  22. 22. VECTOR::PUSH_BACK_NOTHROW void push_back_nothrow(const value_type& val, std::error_condition& ec) { TRY(reallocate_nothrow(size() + 1, ec)); TRY(copy_construct_nothrow(data() + size(), val, ec)); this->m_last += 1; }
  23. 23. COPY_CONSTRUCT_NOTHROW template <typename T> typename std::enable_if<std::is_nothrow_copy_constructible_v<T>>::type copy_construct_nothrow(void* position, const T& val, std::error_condition& /* ec */) { new(position) T(val); } template <typename T> typename std::enable_if<!std::is_nothrow_copy_constructible_v<T>>::type copy_construct_nothrow(void* position, const T& val, std::error_condition& ec) { T* obj = new(position) T(); // NOTE: default ctor obj->assign_copy(val, ec); if (ec) { obj->~T(); } }
  24. 24. C++ WITH EXCEPTIONS library sources Kernel mode driver no exceptions user mode application has exceptions EFI mode driver no exceptions
  25. 25. C++ WITH EXCEPTIONS struct Message { nestl::string id; nestl::vector<int> data; void assign_copy(const Message& other, std::error_condition& ec) { TRY(id.assign_copy(other.id, ec)); TRY(data.assign_copy(other.data, ec)); } };
  26. 26. C++ WITH EXCEPTIONS template <typename T> struct allocator { T* allocate(size_t count); // only if has exceptions void deallocate(T* location, size_t count); // only if has exceptions T* allocate_nothrow(size_t count) noexcept; void deallocate_nothrow(T* location, size_t count) noexcept; }; template <typename Allocator> struct allocator_traits { static pointer allocate(Allocator& a, size_t count); // only if has exceptions static pointer allocate_nothrow(Allocator& a, size_t count) noexcept; };
  27. 27. C++ WITH EXCEPTIONS template <typename T, typename Allocator> struct vector_base { iterator begin(); }; template <typename T, typename Allocator> struct vector_nx : public vector_base<T, Allocator> { void push_back_nothrow(const value_type& val, std::error_condition& ec) noexcept; }; template <typename T, typename Allocator> struct vector_x : public vector_nx<T, Allocator> { void push_back(const value_type& val); };
  28. 28. C++ WITH EXCEPTIONS template <typename VectorBase> struct vector_nx : public VectorBase { void push_back_nothrow(const value_type& val, std::error_condition& ec) noexcept; }; template <typename VectorBase> struct vector_x : public VectorBase { void push_back(const value_type& val); };
  29. 29. C++ WITH EXCEPTIONS struct system_exception_support : std::integral_constant<bool, NESTL_HAS_EXCEPTIONS == 1> { }; template <typename T, typename Allocator = nestl::allocator<T>> using vector = typename or_<system_exception_support::value, vector_x<T, Allocator>, vector_nx<T, Allocator>>::type;
  30. 30. LET'S TALK? alexey.kutumov@gmail.com https://github.com/prograholic/simple_vector

×