The document describes how to implement a std::vector from scratch in C++. It begins with defining the vector interface and types like iterator, size_type, etc. It then describes implementing a vector_base class to handle memory allocation and storage. The rest of the document outlines methods for common vector operations without size modifications like at(), methods for changing the size like reserve(), insert(), and erase(). It provides code snippets and discusses using various Standard Library components to implement the vector functionality.
Антон Бикинеев, Writing good std::future< C++ >Sergey Platonov
В докладе Антон расскажет о грядущих мажорных изменениях языка, которые, не войдя в Стандарт 17-го года и оставшись в Technical Specifications, будут ждать своего мержа в 20-м, а также быть уже реализованными в некоторых компиляторах. Осветятся также минорные, уже одобренные фичи следующего Стандарта, как языковые, так и библиотечные. Антон расскажет об их целях, покажет методы использования, а также осветит некоторые гайдлайны и трики.
Не так давно Гор Нишанов представил свой доклад: C++ Coroutines a negative overhead abstraction. В этом докладе Гор упомянул, что предложенный дизайн корутин позволяет их использовать практически в любых окружениях, в том числе и с "бедным" C++ рантаймом.
Я решил попробовать запустить корутины в следующих окружениях: обычное приложение, драйвер ОС Windows, EFI приложение. Только в одном из этих окружений есть полноценный C++ рантайм и поддержка исключений, в остальных ничего этого нет. Более того, EFI приложение вообще выполняется до старта ОС.
Я хочу рассказать о том, как мне удалось запустить корутины в этих окружениях, поговорим о том, какие проблемы существуют в асинхронном системном программировании и как их можно обойти.
Антон Бикинеев, Writing good std::future< C++ >Sergey Platonov
В докладе Антон расскажет о грядущих мажорных изменениях языка, которые, не войдя в Стандарт 17-го года и оставшись в Technical Specifications, будут ждать своего мержа в 20-м, а также быть уже реализованными в некоторых компиляторах. Осветятся также минорные, уже одобренные фичи следующего Стандарта, как языковые, так и библиотечные. Антон расскажет об их целях, покажет методы использования, а также осветит некоторые гайдлайны и трики.
Не так давно Гор Нишанов представил свой доклад: C++ Coroutines a negative overhead abstraction. В этом докладе Гор упомянул, что предложенный дизайн корутин позволяет их использовать практически в любых окружениях, в том числе и с "бедным" C++ рантаймом.
Я решил попробовать запустить корутины в следующих окружениях: обычное приложение, драйвер ОС Windows, EFI приложение. Только в одном из этих окружений есть полноценный C++ рантайм и поддержка исключений, в остальных ничего этого нет. Более того, EFI приложение вообще выполняется до старта ОС.
Я хочу рассказать о том, как мне удалось запустить корутины в этих окружениях, поговорим о том, какие проблемы существуют в асинхронном системном программировании и как их можно обойти.
SIMD machines — machines capable of evaluating the same instruction on several elements of data in parallel — are nowadays commonplace and diverse, be it in supercomputers, desktop computers or even mobile ones. Numerous tools and libraries can make use of that technology to speed up their computations, yet it could be argued that there is no library that provides a satisfying minimalistic, high-level and platform-agnostic interface for the C++ developer.
На протяжении всего существования C++ тема компайл-тайм рефлексии поднимается постоянно, но, к сожалению, до сих пор Стандарт языка не дает достаточных возможностей для извлечения и манипулирования компайл-тайм информацией. Большое количество библиотек и препроцессоров было придумано для того, чтобы решить эту проблему, начиная от простых макросов и заканчивая Qt-moc или ODB. В докладе Антон расскажет о том, как на эту проблему смотрит Комитет по Стандартизации: какие решения были предложены, и какое стало доминирующим.
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itSergey Platonov
The talk will look at limitations of compilers when creating fast code and how to make more effective use of both the underlying micro-architecture of modern CPU's and how algorithmic optimizations may have surprising effects on the generated code. We shall discuss several specific CPU architecture features and their pros and cons in relation to creating fast C++ code. We then expand with several algorithmic techniques, not usually well-documented, for making faster, compiler friendly, C++.
Note that we shall not discuss caching and related issues here as they are well documented elsewhere.
Дмитрий Демчук. Кроссплатформенный краш-репортSergey Platonov
Доклад будет посвящен возможностям библиотеки Google Breakpad по созданию краш-репорта. Посмотрим как это работает изнутри.
На примерах будут рассмотрены способы интеграции библиотеки на разных платформах Windows, Linux, Max OS.
C++20 comes with some big new language features: modules, coroutines, concepts, spaceship, and many new libraries. But apart from all those, C++20 also offers many small language improvements, making C++ more powerful and expressive, but also safer and more consistent. This talk is an overview over all those smaller additions to the core language that will make your life easier. We will discuss much-needed improvements to existing facilities such as lambdas, CTAD, structured bindings, and initialisation, as well as brand-new language utilities that you may not yet have heard about!
SIMD machines — machines capable of evaluating the same instruction on several elements of data in parallel — are nowadays commonplace and diverse, be it in supercomputers, desktop computers or even mobile ones. Numerous tools and libraries can make use of that technology to speed up their computations, yet it could be argued that there is no library that provides a satisfying minimalistic, high-level and platform-agnostic interface for the C++ developer.
На протяжении всего существования C++ тема компайл-тайм рефлексии поднимается постоянно, но, к сожалению, до сих пор Стандарт языка не дает достаточных возможностей для извлечения и манипулирования компайл-тайм информацией. Большое количество библиотек и препроцессоров было придумано для того, чтобы решить эту проблему, начиная от простых макросов и заканчивая Qt-moc или ODB. В докладе Антон расскажет о том, как на эту проблему смотрит Комитет по Стандартизации: какие решения были предложены, и какое стало доминирующим.
Evgeniy Muralev, Mark Vince, Working with the compiler, not against itSergey Platonov
The talk will look at limitations of compilers when creating fast code and how to make more effective use of both the underlying micro-architecture of modern CPU's and how algorithmic optimizations may have surprising effects on the generated code. We shall discuss several specific CPU architecture features and their pros and cons in relation to creating fast C++ code. We then expand with several algorithmic techniques, not usually well-documented, for making faster, compiler friendly, C++.
Note that we shall not discuss caching and related issues here as they are well documented elsewhere.
Дмитрий Демчук. Кроссплатформенный краш-репортSergey Platonov
Доклад будет посвящен возможностям библиотеки Google Breakpad по созданию краш-репорта. Посмотрим как это работает изнутри.
На примерах будут рассмотрены способы интеграции библиотеки на разных платформах Windows, Linux, Max OS.
C++20 comes with some big new language features: modules, coroutines, concepts, spaceship, and many new libraries. But apart from all those, C++20 also offers many small language improvements, making C++ more powerful and expressive, but also safer and more consistent. This talk is an overview over all those smaller additions to the core language that will make your life easier. We will discuss much-needed improvements to existing facilities such as lambdas, CTAD, structured bindings, and initialisation, as well as brand-new language utilities that you may not yet have heard about!
An introduction to pointers and references in C++ (with elements of C++11 and C++14). The presentation introduces the readers to the concepts of pointers and references through the pragmatic need of writing a swap function between integers. Generic programming notions (e.g., type constructors) are adopted when useful for the explanation.
Доклад вводит в рассмотрение универсальный адаптер, позволяющий обернуть любой класс с целью добавления новых свойств, отсутствующих в оригинальном классе. Получаемые классы могут иметь в точности такой же интерфейс, как и первоначальные, что позволяет прозрачно заменять их и оборачивать любое количество раз.
Это позволяет добавлять необходимые свойства объектам, не переписывая его с нуля. Предложенная обобщенная концепция будет последовательно введена и проиллюстрирована простыми, но интересными примерами.
Использование юнит-тестов для повышения качества разработкиvictor-yastrebov
В докладе рассмотрены подходы к созданию надежных юнит-тестов, которые просты в поддержке и модернизации, а также принципы создания кода пригодного для покрытия автотестами. Приведены два способа внедрения зависимости: с использованием конструктора тестируемого объекта, а также с использованием подхода "выделить и переопределить". Каждый из способов разобран на примере, демонстрирующем особенности его реализации и применения. Приведен ряд практических советов, нацеленных на создание надежных юнит-тестов. Использование на практике приведенных подходов и принципов позволяет упростить процесс поддержки и модификации существующего кода, а также дает уверенность в надежности работы добавляемого нового функционала. В конечном итоге это приводит к повышению качества разрабатываемого продукта.
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и JavascriptSergey Platonov
Шаблоны — мощный инструмент, добавляющий в язык новые возможности, а программистам в команде — новые проблемы. Доклад покажет, как тщательно продуманный шаблонный код может не усложнить, а упростить жизнь и дать надёжную абстракцию межпроцессных межъязыковых асинхронных вызовов функций. С помощью шаблонов можно:
адаптировать Promise/A+ из Javascript для C++
автоматически проверять и раскладывать динамический массив аргументов на статичные аргументы функции
сделать аналог std::bind для weak_ptr.
Эти вещи будут показаны на примере взаимных вызовов между C++ и Javascript в одном приложении с помощью CEF3.
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...Platonov Sergey
Кто-то верно подметил, что разработчики статических анализатора часто сталкиваются с "проблемой айсберга". Им сложно объяснить разработчикам, почему сложно написать и развивать статические анализаторы кода. Дело в том, что сторонние наблюдатели видят только вершину всего процесса, так как им доступен для изучения только простой интерфейс, который предоставляют анализаторы для взаимодействия с миром. Это ведь не графический редактор с сотнями кнопок и рычажков. В результате и возникает ощущение, что раз прост интерфейс взаимодействия, то и прост продукт. На самом деле статические анализаторы кода — это сложные программы, в которых живут и взаимодействуют разнообразнейшие методы поиска дефектов. В них реализуется множество экспертные системы, выдающие заключения о коде на основе как точных, так и эмпирических алгоритмах. В парном докладе, основатели анализатора PVS-Studio расскажут о том, как незаметно потратить 10 лет, чтобы написать хороший анализатор. Дьявол кроется в деталях!
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионаловSergey Platonov
В докладе перед нами откроется великолепный мир велосипедов и устаревших технологий, которые люди продолжают переносить в новые проекты и повсеместно использовать. Мы поговорим о:
Copy-On-Write
разработке без оглядки на готовые решения и к чему это приводит
force inline
оптимизациях, которые отлично себя показывают на бенчмарках и плохо себя ведут в реальной жизни
бездумно отключаемых оптимизациях компилятора
тонкостях стандартной библиотеки для повседневного использования
супер качественном велосипедостроении
Догнать и перегнать boost::lexical_castRoman Orlov
Разбор нестандартной реализации преобразования целого числа в строку без использования циклов и рекурсивных вызовов времени исполнения - только рекурсия на этапе компиляции
В своих прошлых докладах (http://cpp-russia.ru/?p=198, и http://cpp-russia.ru/?page_id=1239) я рассказывал о C++ без исключений, как с эти жить, как работать. Этот доклад является продолжением этой серии. Я рекомендую освежить в памяти предыдущие доклады, чтобы наша работа была более продуктивной. Мы обсудим механизмы создания, копирования и перемещения объектов, механизмы аллокации и деаллокации памяти, а также обработку ошибок и исключений. Также мы обсудим проблемы и неудобства, которые испытывает программист, когда пишет код без исключений. В конце, я попытаюсь показать, как можно проектировать структуры данных, контейнеры для удобной работы в средах с исключениями и без исключений.
Фитнес для вашего кода: как держать его в формеIlia Shishkov
C++ Россия 2017
Во время моего выступления мы поговорим о принципе "Minimize coupling, maximize cohesion". Обсудим, что это такое и что значат эти непонятные слова. Кроме того на приближенном к реальности примере мы рассмотрим, как, применяя указанный принцип, можно держать ваш код в форме, чтобы он был готов ко всем неожиданностям, которые подстерегают ваш проект в течение его жизни.
HexRaysCodeXplorer: object oriented RE for fun and profitAlex Matrosov
HexRaysCodeXplorer - Hex-Rays Decompiler plugin for easier code navigation. Here are the main features of the plugin:
- Automatic type REconstruction for C++ objects.
- C-tree graph visualization - a special tree-like structure representing a decompiled routine in c_itemt terms. Useful feature for understanding how the decompiler works.
- Navigation through virtual function calls in HexRays Pseudocode window.
- Object Explorer - useful interface for navigation through virtual tables (VTBL) structures.
In this presentation, the authors of HexRaysCodeXplorer will be discussing main functionality of the plugin and its application for reverse engineering. The authors will be presenting the algorithm for C++ type REconstruction. Also a special version of HexRaysCodeXplorer (H2HC edition) will be released with new features developed specially for H2Cconference. New features will be committed to GitHub from the stage.
Fuzzing is a software testing technique that involves providing invalid, unexpected, or random data to the inputs of a computer program. The presentation covers types of fuzzers and describes how they work. We will write and run a real fuzzer. Also it shows how fuzzers can guess correct CRC checksums, help with regression testing and find logical bugs in programs. Finally, it summarizes fuzzing usage at Google.
Василий Сорокин, Простой REST сервер на Qt с рефлексиейSergey Platonov
Библиотека Qt имеет довольно мощную систему рефлексии. На примере простого в использовании класса, позволяющего с помощью наследования быстро построить REST сервер под ваши нужды, я покажу как элегантно ее можно задействовать в реальной жизни. В заключительной части, покажу еще один пример когда рефлексия Qt помогает красиво протестировать испускание сигналов классом.
C++ code, please help! RESPOND W COMPLETED CODE PLEASE, am using V.pdfrahulfancycorner21
C++ code, please help! RESPOND W/ COMPLETED CODE PLEASE, am using Visual Studio
Code.
Error message:
ld: Undefined symbols:
parseName(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::init(), referenced from:
_main in module-a187a7.o
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::insert(std::__1::basic_string, std::__1::allocator>, int), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SubExpression::parse(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
_main in module-a187a7.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[Done] exited with code=1 in 1.478 seconds
divide.h
class Divide : public SubExpression
{
public:
//define the default construtor
Divide(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//divide the value of left and value of the right
//and return the value.
return left->evaluate() / right->evaluate();
}
};
expression.h
// Expression
class Expression
{
public:
//declare a virtual function evaluate()
virtual int evaluate() = 0;
};
literal.h
//Operand
class Literal : public Operand
{
public:
//define the construtor
Literal(int value)
{
this->value = value;
}
//define the function evaluate()
//returns the value
int evaluate()
{
return value;
}
private:
int value;
};
minus.h
//define the class Minus subclass of the SubExpression
class Minus : public SubExpression
{
public:
//define the default construtor
Minus(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//subtract the value of right from the value of the left
//and return the value.
return left->evaluate() - right->evaluate();
}
};
module.cpp
#include
#include
#include
#include
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
//create an object of SymbolTable
SymbolTable symbolTable;
//prototype of the function
void parseAssignments(stringstream& in);
//define main function
int main()
{
// declare the variables
Expression* expression;
char paren, comma;
string line;
// create an input file stream
ifstream fin("input.txt");
// check, if the file is not opened
//then display a error message
if (!fin.is_open())
perror("error while opening file");
//use a loop, to read the content from the file
while (getline(fin, line))
{
symbolTable.init();
if (!fin)
break;
stringstream in(line, ios_base::in);
in >> paren;
cout << line << " ";
expression = SubExpression::parse(in);
in >> comma;
//call the function
parseAssignments(in);
//Display the result
int result = expression->evaluate();
cout << "Value = " << result << endl;
}
system("pause");
return 0;
}
//definition of the function p.
C++ code, please help! Troubleshooting and cannot for the life of me.pdfrahulfancycorner21
C++ code, please help! Troubleshooting and cannot for the life of me figure it out. I am using
Visual Studio Code.
Error message:
ld: Undefined symbols:
parseName(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::init(), referenced from:
_main in module-a187a7.o
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SymbolTable::insert(std::__1::basic_string, std::__1::allocator>, int), referenced from:
parseAssignments(std::__1::basic_stringstream, std::__1::allocator>&) in module-a187a7.o
SubExpression::parse(std::__1::basic_stringstream, std::__1::allocator>&), referenced from:
_main in module-a187a7.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
[Done] exited with code=1 in 1.478 seconds
divide.h
class Divide : public SubExpression
{
public:
//define the default construtor
Divide(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//divide the value of left and value of the right
//and return the value.
return left->evaluate() / right->evaluate();
}
};
expression.h
// Expression
class Expression
{
public:
//declare a virtual function evaluate()
virtual int evaluate() = 0;
};
literal.h
//Operand
class Literal : public Operand
{
public:
//define the construtor
Literal(int value)
{
this->value = value;
}
//define the function evaluate()
//returns the value
int evaluate()
{
return value;
}
private:
int value;
};
minus.h
//define the class Minus subclass of the SubExpression
class Minus : public SubExpression
{
public:
//define the default construtor
Minus(Expression* left, Expression* right) : SubExpression(left, right)
{
}
//define the function evaluate()
int evaluate()
{
//subtract the value of right from the value of the left
//and return the value.
return left->evaluate() - right->evaluate();
}
};
module.cpp
#include
#include
#include
#include
#include
using namespace std;
#include "expression.h"
#include "subexpression.h"
#include "symboltable.h"
#include "parse.h"
//create an object of SymbolTable
SymbolTable symbolTable;
//prototype of the function
void parseAssignments(stringstream& in);
//define main function
int main()
{
// declare the variables
Expression* expression;
char paren, comma;
string line;
// create an input file stream
ifstream fin("input.txt");
// check, if the file is not opened
//then display a error message
if (!fin.is_open())
perror("error while opening file");
//use a loop, to read the content from the file
while (getline(fin, line))
{
symbolTable.init();
if (!fin)
break;
stringstream in(line, ios_base::in);
in >> paren;
cout << line << " ";
expression = SubExpression::parse(in);
in >> comma;
//call the function
parseAssignments(in);
//Display the result
int result = expression->evaluate();
cout << "Value = " << result << endl;
}
system("pause");
return 0;
}
/.
c++ pointers by Amir Hamza Khan (SZABISTIAN)Ameer Hamxa
This slides will help you to learn pointers in c++ and i have put in some programs in this slides to help beginners in c++ and also you can use it as your own presentation lol ;)
follow me on facebook https://www.facebook.com/Ameerii132
and you are welcome for questions and quirries
Please complete ALL of the �TO DO�s in this code. I am really strugg.pdfsupport58
Please complete ALL of the TO DOs in this code. I am really struggling with this assignment.
The last time I posted this question, they did not complete them all. Please do it! There are two
files, list.h and queue.h. I tried to complete this on my own and none of it worked, so I am
posting the template again instead of my nonworking code. Please do not use chatgpt, I think the
last person used it.
list.h:
#pragma once
#include // size_t
#include // std::bidirectional_iterator_tag
#include // std::is_same, std::enable_if
template
class List {
private:
struct Node {
Node *next, *prev;
T data;
explicit Node(Node* prev = nullptr, Node* next = nullptr)
: next{next}, prev{prev} {}
explicit Node(const T& data, Node* prev = nullptr, Node* next = nullptr)
: next{next}, prev{prev}, data{data} {}
explicit Node(T&& data, Node* prev = nullptr, Node* next = nullptr)
: next{next}, prev{prev}, data{std::move(data)} {}
};
template
class basic_iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = ptrdiff_t;
using pointer = pointer_type;
using reference = reference_type;
private:
friend class List;
using Node = typename List::Node;
Node* node;
explicit basic_iterator(Node* ptr) noexcept : node{ptr} {}
explicit basic_iterator(const Node* ptr) noexcept : node{const_cast(ptr)} {}
public:
basic_iterator() { /* TODO */ };
basic_iterator(const basic_iterator&) = default;
basic_iterator(basic_iterator&&) = default;
~basic_iterator() = default;
basic_iterator& operator=(const basic_iterator&) = default;
basic_iterator& operator=(basic_iterator&&) = default;
reference operator*() const {
// TODO
}
pointer operator->() const {
// TODO
}
// Prefix Increment: ++a
basic_iterator& operator++() {
// TODO
}
// Postfix Increment: a++
basic_iterator operator++(int) {
// TODO
}
// Prefix Decrement: --a
basic_iterator& operator--() {
// TODO
}
// Postfix Decrement: a--
basic_iterator operator--(int) {
// TODO
}
bool operator==(const basic_iterator& other) const noexcept {
// TODO
}
bool operator!=(const basic_iterator& other) const noexcept {
// TODO
}
};
public:
using value_type = T;
using size_type = size_t;
using difference_type = ptrdiff_t;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using iterator = basic_iterator;
using const_iterator = basic_iterator;
private:
Node head, tail;
size_type _size;
public:
List() {
// TODO - Don't forget to initialize the list beforehand
}
List( size_type count, const T& value ) {
// TODO - Don't forget initialize the list beforehand
}
explicit List( size_type count ) {
// TODO - Don't forget initialize the list beforehand
}
List( const List& other ) {
// TODO - Don't forget initialize the list beforehand
}
List( List&& other ) {
// TODO - Don't forget initialize the list beforehand
}
~List() {
// TODO
}
List& operator=( const List& other ) {
// TODO
}
List& operator=( List&& o.
This presentation considers certain specific features of C++11 and additions to STL library (uniform initialization, new containers and methods, move semantics).
Presentation by Taras Protsiv (Software Engineer, GlobalLogic), Kyiv, delivered at GlobalLogic C++ TechTalk in Lviv, September 18, 2014.
More details -
http://www.globallogic.com.ua/press-releases/lviv-cpp-techtalk-coverage
Павел Филонов, Разделяй и управляй вместе с Conan.ioSergey Platonov
Несмотря на солидный возраст С++, одной из больших проблем, возникающих при разработке с его использованием, до сих пор является управление зависимостям. Особенно остро этот вопрос возникает при наличии нескольких различных целевых платформ. В докладе будет рассмотрено, как менеджер пакетов Conan.io позволяет решить проблему управления зависимостями и, как следствие, значительно улучшить скорость разработки на C++ и повысить модульность разрабатываемых систем.
Григорий Демченко, Асинхронность и неблокирующая синхронизацияSergey Platonov
Практика показывает, что использование подхода, основанного на колбеках для асинхронного программирования обычно не является удобным и подвержено различным ошибкам. Для упрощения написания и поддержки сложных асинхронных программ можно использовать несколько иной подход: использовать сопрограммы для переключения контекста на время ожидания события. Такой подход позволяет реализовать интересные неблокирующие примитивы, включая неблокирующее сетевое взаимодействие, неблокирующие мьютексы, а также удобное переключение между различными пулами потоков для разнесения выполнения задач, которые требуют различные ресурсы.
Хочется чего-то новенького, необычного? Тогда добро пожаловать в мир чудеc C++17:
if constexpr (auto& [number, ok] = variable; ok)
return "Hi"
else
return number + 42;
Вы услышите о новом стандарте C++, обнаружите для себя новые полезные классы, функции и возможности языка. Для каждой новинки я приведу примеры использования, расскажу о нюансах и подводных камнях.
А ещё вы узнаете о том, как проходят заседания комитета по стандартизации C++ и сможете задать интересующие вас вопросы связанные с нововведениями С++17 и С++Next.
Павел Беликов, Как избежать ошибок, используя современный C++Sergey Platonov
Одной из проблем C++ является большое количество конструкций, поведение которых не определено или просто неожиданно для программиста. С такими ошибками мы часто сталкиваемся при разработке статического анализатора кода. Но, как известно, лучше всего находить ошибки ещё на этапе компиляции. На этом докладе мы поговорим о том, какие техники из современного C++ позволяют писать не только более простой и выразительный, но и безопасный код. Вы увидите ошибки в коде различных Open Source проектов и узнаете, как можно их избежать, используя новые стандарты
Тестирование графического интерфейса пользователя является одним из основных видов тестирования графических приложений. В докладе будут рассмотрены задачи и особенности такого тестирования.
Далее будут рассмотрены плюсы и минусы использования стандартной Qt библиотеки QTest, и представлен проект QSpec, как альтернатива QTest. Также будут представлены примеры использования QSpec и дальнейшие планы по развитию этого проекта.
Адрес проекта: https://github.com/ugeneunipro/QSpec
Илья Шишков, Принципы создания тестируемого кодаSergey Platonov
В докладе рассмотрено зачем нужно покрывать код автотестами и почему многие этого до сих пор не делают. Что такое хорошие юнит-тесты и какую пользу они дают помимо собственно тестирования. Три принципа организации кода, упрощающие создание юнит-тестов: закон Деметры, внедрение зависимости и принцип единой ответственности. Каждый принцип разобран на примере, демонстрирующем его применение и получаемые при этом преимущества.
Антон Наумович, Система автоматической крэш-аналитики своими средствамиSergey Platonov
В докладе будет рассмотрена система контроля качества с помощью снятия и анализа крэшдамп-файлов (применительно в первую очередь к системе Windows). Будет представлена архитектура и инструментарий для организации автоматического сбора и анализа крэшдамп-файлов, снимаемых в момент возникновения проблем в приложениях (падения, зависания, превышение потребления ресурсов – памяти, файловых дескрипторов и т.д.)
Андрей Карпов, Приватные байки от разработчиков анализатора кодаSergey Platonov
Доклад о редких нестандартных расширениях языка С++, про которые никто не знает, но которые надо поддерживать в анализаторе кода.
О магии Visual C++ с файлом stdafx.h, когда проект компилируется, хотя не должен. О том как зародился viva64 (предшественник PVS-Studio) для поиска 64-битных проблем. Как и почему исчез анализ кода, который одно время существовал в компиляторе Intel C++.
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
В последнее время в промышленной разработке ПО особую популярность обретают Domain-Specific Lanugages (DSL). Они драматически упрощают разработку и дают возможность “программировать” не только программистам, но и пользователям прикладных программ.
В своем докладе я расскажу об опыте использования DSL применительно к С++, причем упор будет сделан на производительность кода DSL, и его мгновенную “встраиваемость” в запущенную программу путем компиляции DSL-кода в нативный код с помощью инструментария LLVM.
Transform Your Communication with Cloud-Based IVR SolutionsTheSMSPoint
Discover the power of Cloud-Based IVR Solutions to streamline communication processes. Embrace scalability and cost-efficiency while enhancing customer experiences with features like automated call routing and voice recognition. Accessible from anywhere, these solutions integrate seamlessly with existing systems, providing real-time analytics for continuous improvement. Revolutionize your communication strategy today with Cloud-Based IVR Solutions. Learn more at: https://thesmspoint.com/channel/cloud-telephony
Software Engineering, Software Consulting, Tech Lead, Spring Boot, Spring Cloud, Spring Core, Spring JDBC, Spring Transaction, Spring MVC, OpenShift Cloud Platform, Kafka, REST, SOAP, LLD & HLD.
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI AppGoogle
AI Fusion Buddy Review: Brand New, Groundbreaking Gemini-Powered AI App
👉👉 Click Here To Get More Info 👇👇
https://sumonreview.com/ai-fusion-buddy-review
AI Fusion Buddy Review: Key Features
✅Create Stunning AI App Suite Fully Powered By Google's Latest AI technology, Gemini
✅Use Gemini to Build high-converting Converting Sales Video Scripts, ad copies, Trending Articles, blogs, etc.100% unique!
✅Create Ultra-HD graphics with a single keyword or phrase that commands 10x eyeballs!
✅Fully automated AI articles bulk generation!
✅Auto-post or schedule stunning AI content across all your accounts at once—WordPress, Facebook, LinkedIn, Blogger, and more.
✅With one keyword or URL, generate complete websites, landing pages, and more…
✅Automatically create & sell AI content, graphics, websites, landing pages, & all that gets you paid non-stop 24*7.
✅Pre-built High-Converting 100+ website Templates and 2000+ graphic templates logos, banners, and thumbnail images in Trending Niches.
✅Say goodbye to wasting time logging into multiple Chat GPT & AI Apps once & for all!
✅Save over $5000 per year and kick out dependency on third parties completely!
✅Brand New App: Not available anywhere else!
✅ Beginner-friendly!
✅ZERO upfront cost or any extra expenses
✅Risk-Free: 30-Day Money-Back Guarantee!
✅Commercial License included!
See My Other Reviews Article:
(1) AI Genie Review: https://sumonreview.com/ai-genie-review
(2) SocioWave Review: https://sumonreview.com/sociowave-review
(3) AI Partner & Profit Review: https://sumonreview.com/ai-partner-profit-review
(4) AI Ebook Suite Review: https://sumonreview.com/ai-ebook-suite-review
#AIFusionBuddyReview,
#AIFusionBuddyFeatures,
#AIFusionBuddyPricing,
#AIFusionBuddyProsandCons,
#AIFusionBuddyTutorial,
#AIFusionBuddyUserExperience
#AIFusionBuddyforBeginners,
#AIFusionBuddyBenefits,
#AIFusionBuddyComparison,
#AIFusionBuddyInstallation,
#AIFusionBuddyRefundPolicy,
#AIFusionBuddyDemo,
#AIFusionBuddyMaintenanceFees,
#AIFusionBuddyNewbieFriendly,
#WhatIsAIFusionBuddy?,
#HowDoesAIFusionBuddyWorks
GraphSummit Paris - The art of the possible with Graph TechnologyNeo4j
Sudhir Hasbe, Chief Product Officer, Neo4j
Join us as we explore breakthrough innovations enabled by interconnected data and AI. Discover firsthand how organizations use relationships in data to uncover contextual insights and solve our most pressing challenges – from optimizing supply chains, detecting fraud, and improving customer experiences to accelerating drug discoveries.
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Crescat
Crescat is industry-trusted event management software, built by event professionals for event professionals. Founded in 2017, we have three key products tailored for the live event industry.
Crescat Event for concert promoters and event agencies. Crescat Venue for music venues, conference centers, wedding venues, concert halls and more. And Crescat Festival for festivals, conferences and complex events.
With a wide range of popular features such as event scheduling, shift management, volunteer and crew coordination, artist booking and much more, Crescat is designed for customisation and ease-of-use.
Over 125,000 events have been planned in Crescat and with hundreds of customers of all shapes and sizes, from boutique event agencies through to international concert promoters, Crescat is rigged for success. What's more, we highly value feedback from our users and we are constantly improving our software with updates, new features and improvements.
If you plan events, run a venue or produce festivals and you're looking for ways to make your life easier, then we have a solution for you. Try our software for free or schedule a no-obligation demo with one of our product specialists today at crescat.io
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Mind IT Systems
Healthcare providers often struggle with the complexities of chronic conditions and remote patient monitoring, as each patient requires personalized care and ongoing monitoring. Off-the-shelf solutions may not meet these diverse needs, leading to inefficiencies and gaps in care. It’s here, custom healthcare software offers a tailored solution, ensuring improved care and effectiveness.
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Łukasz Chruściel
No one wants their application to drag like a car stuck in the slow lane! Yet it’s all too common to encounter bumpy, pothole-filled solutions that slow the speed of any application. Symfony apps are not an exception.
In this talk, I will take you for a spin around the performance racetrack. We’ll explore common pitfalls - those hidden potholes on your application that can cause unexpected slowdowns. Learn how to spot these performance bumps early, and more importantly, how to navigate around them to keep your application running at top speed.
We will focus in particular on tuning your engine at the application level, making the right adjustments to ensure that your system responds like a well-oiled, high-performance race car.
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeAftab Hussain
Understanding variable roles in code has been found to be helpful by students
in learning programming -- could variable roles help deep neural models in
performing coding tasks? We do an exploratory study.
- These are slides of the talk given at InteNSE'23: The 1st International Workshop on Interpretability and Robustness in Neural Software Engineering, co-located with the 45th International Conference on Software Engineering, ICSE 2023, Melbourne Australia
Atelier - Innover avec l’IA Générative et les graphes de connaissancesNeo4j
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Allez au-delà du battage médiatique autour de l’IA et découvrez des techniques pratiques pour utiliser l’IA de manière responsable à travers les données de votre organisation. Explorez comment utiliser les graphes de connaissances pour augmenter la précision, la transparence et la capacité d’explication dans les systèmes d’IA générative. Vous partirez avec une expérience pratique combinant les relations entre les données et les LLM pour apporter du contexte spécifique à votre domaine et améliorer votre raisonnement.
Amenez votre ordinateur portable et nous vous guiderons sur la mise en place de votre propre pile d’IA générative, en vous fournissant des exemples pratiques et codés pour démarrer en quelques minutes.
Graspan: A Big Data System for Big Code AnalysisAftab Hussain
We built a disk-based parallel graph system, Graspan, that uses a novel edge-pair centric computation model to compute dynamic transitive closures on very large program graphs.
We implement context-sensitive pointer/alias and dataflow analyses on Graspan. An evaluation of these analyses on large codebases such as Linux shows that their Graspan implementations scale to millions of lines of code and are much simpler than their original implementations.
These analyses were used to augment the existing checkers; these augmented checkers found 132 new NULL pointer bugs and 1308 unnecessary NULL tests in Linux 4.4.0-rc5, PostgreSQL 8.3.9, and Apache httpd 2.2.18.
- Accepted in ASPLOS ‘17, Xi’an, China.
- Featured in the tutorial, Systemized Program Analyses: A Big Data Perspective on Static Analysis Scalability, ASPLOS ‘17.
- Invited for presentation at SoCal PLS ‘16.
- Invited for poster presentation at PLDI SRC ‘16.
Mobile App Development Company In Noida | Drona InfotechDrona Infotech
Looking for a reliable mobile app development company in Noida? Look no further than Drona Infotech. We specialize in creating customized apps for your business needs.
Visit Us For : https://www.dronainfotech.com/mobile-application-development/
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxrickgrimesss22
Discover the essential features to incorporate in your Winzo clone app to boost business growth, enhance user engagement, and drive revenue. Learn how to create a compelling gaming experience that stands out in the competitive market.
Utilocate offers a comprehensive solution for locate ticket management by automating and streamlining the entire process. By integrating with Geospatial Information Systems (GIS), it provides accurate mapping and visualization of utility locations, enhancing decision-making and reducing the risk of errors. The system's advanced data analytics tools help identify trends, predict potential issues, and optimize resource allocation, making the locate ticket management process smarter and more efficient. Additionally, automated ticket management ensures consistency and reduces human error, while real-time notifications keep all relevant personnel informed and ready to respond promptly.
The system's ability to streamline workflows and automate ticket routing significantly reduces the time taken to process each ticket, making the process faster and more efficient. Mobile access allows field technicians to update ticket information on the go, ensuring that the latest information is always available and accelerating the locate process. Overall, Utilocate not only enhances the efficiency and accuracy of locate ticket management but also improves safety by minimizing the risk of utility damage through precise and timely locates.
Launch Your Streaming Platforms in MinutesRoshan Dwivedi
The claim of launching a streaming platform in minutes might be a bit of an exaggeration, but there are services that can significantly streamline the process. Here's a breakdown:
Pros of Speedy Streaming Platform Launch Services:
No coding required: These services often use drag-and-drop interfaces or pre-built templates, eliminating the need for programming knowledge.
Faster setup: Compared to building from scratch, these platforms can get you up and running much quicker.
All-in-one solutions: Many services offer features like content management systems (CMS), video players, and monetization tools, reducing the need for multiple integrations.
Things to Consider:
Limited customization: These platforms may offer less flexibility in design and functionality compared to custom-built solutions.
Scalability: As your audience grows, you might need to upgrade to a more robust platform or encounter limitations with the "quick launch" option.
Features: Carefully evaluate which features are included and if they meet your specific needs (e.g., live streaming, subscription options).
Examples of Services for Launching Streaming Platforms:
Muvi [muvi com]
Uscreen [usencreen tv]
Alternatives to Consider:
Existing Streaming platforms: Platforms like YouTube or Twitch might be suitable for basic streaming needs, though monetization options might be limited.
Custom Development: While more time-consuming, custom development offers the most control and flexibility for your platform.
Overall, launching a streaming platform in minutes might not be entirely realistic, but these services can significantly speed up the process compared to building from scratch. Carefully consider your needs and budget when choosing the best option for you.
Добрый день, меня зовут Алексей Кутумов, я являюсь старшим разработчиком в ЛК
План:
Что я хочу показать:
Представим, что мы разработчики стандартной библиотеки C++, что нам нужно от стандартной библиотеки, чтобы мы смогли реализовать std::vector.
В этом докладе мы возьмем только компилятор (я делал с помощью компилятора из MSVS 2015 – cl.exe версии 19). Он довольно хорошо умеет C++11 и, возможно, что-то из C++14. И сами построим свою стандартную библиотеку.
Вообще, изначально, я хотел сделать основной целью доклада мысль, что реализовать std::vector – это просто. Но потом я подумал, и понял, что это неинтересно. Ну, во-первых, это действительно просто сделать (как мне кажется), ну а во-вторых, это не совсем интересно. Понятно, что упрощение реализации неизменно ведет к сужению кейсов использования, или ухудшении производительности, ухудшении гарантий и т.д. В конце концов, int* x = new int[10], чем не вектор?
Итак, какой у нас план:
Сначала мы осмотрим интерфейс нашего вектора – только декларацию, и посмотрим, что-же из стандартной библиотеки нам нужно, чтобы задекларировать интерфейс вектора.
Затем, мы будем реализовывать вектор. Придумаем такую штуку как vector_base, поймем, для чего она нужна.
После этого, мы пойдем реализовывать вектор потихоньку.
Начнем сначала с методов, которые не изменяют размер вектора.
Потом реализуем метод reserve, поговорим подробнее о гарантиях, которые он дает, и как мы их достигаем.
Потом реализуем метод insert, который вставляет один элемент, поговорим о его гарантиях.
Затем реализуем insert с парой итераторов.
Затем реализуем insert с n элементами.
После этого, реализуем erase с парой итераторов.
А после этого, внезапно, реализуем весь остальной функционал вектора.
Вот так выглядит декларация вектора, наверняка все знают, даже наверное наизусть эту декларацию.
Итак, давайте я еще раз поясню, я буду показывать какие-то куски кода, потом мы будем разбирать все конструкции, которые в этом куске кода есть, при этом, будут появляться новые куски кода, в общем, вот такая рекурсия.
Да, и еще, если не сказано обратное, то по умолчаию считаем, что мы находимся внутри пространства std
Итак, тут нам все понятно – два параметра шаблона.
Первый параметр – это тип объектов, которые будут храниться в векторе
Второй параметр – это аллокатор, он имеет значение по умолчанию – стандартный аллокатор.
Итак, мы плавно переходим к обсуждению аллокаторов.
Здесь представлен интерфейс аллокатора, как видно, здесь тоже нет никаких сложностей.
От аллокатора требуется совсем немного, суметь выделить и удалить память, ну и кроме этого, объявить тип value_type. Кто нибудь смотрел доклад Александреску про аллокаторы? Поднимите руки.
Отлично, тогда следующий вопрос вы пропускаете.
Итак, вопрос, кто нибудь знает, зачем изначально были придуманы аллокаторы? Изначально аллокаторы были придуманы Александром Степановым для того чтобы контейнеры не зависели от модели памяти (если кто знает, то в 16-битном режиме есть разные типы указателей, near pointer, far pointer). Как раз аллокаторы абстрагировали это знание предоставлением нужного типа указателей и механизма аллокации и деаллокации памяти.
В С++11 ввели понятие minimal allocator interface, теперь от аллокатора требуется совсем немного обязательных вещей:
Объявить value_type – тип объектов, которые аллоцируются этим аллокатором.
Объявить функции allocate и deallocate для управления памятью.
Итак, с аллокатором тоже все понятно. В принципе, мы можем даже предоставить реализацию этого аллокатора
Снова возвращаемся к вектору.
Итак, давайте поговорим про типы, которые вектор предоставляет клиентам. Я опустил заголовок класса и разбил декларации типов на два слайда.
Итак, на этом слайде представлены типы, которые отдаются на откуп реализации.
Давайте вспомним, какие требования стандарт предъявляет к этим типам?
Давайте сначала поговорим про difference_type и size_type
Какие требования стандарт предъявляет к двум следующим типам?
difference_type – это должен быть тем же самым типом что и тип, значение которого возвращается при вычислении разницы двух итераторов.
size_type – это тип, который может представить любое неотрицательное число типа difference_type
Кто знает, какие требования к типу итератора предъявляет стандарт? Итератор должен удовлетворять модели (или концепту) RandomAccessIterator.
Что самое простое подходит – обычный указатель, его и возьмем.
Итого, для этих типов, мы выбираем самую простую реализацию, которая удовлетворяет всем требованиям.
В принципе, нас эта полностью устраивает.
Теперь, что касается остальных типов. С одной стороны все проще, в стандарте явно прописано, что эти типы должны быть такими, как указано на этом слайде.
Я уверен, многие из вас знакомы с std::reverse_iterator, поднимите руки, кто знает что такое reverse_iterator?
Отлично, тогда, я думаю, нет смысла подробно объяснять что это такое – это адаптер, который сам является итератором – он определяет операции инкремента, декремента, сравнения и т.д. Но при этом, операции инкремента и декремента работают противоположным образом по сравнению с базовым итератором – в обратную сторону.
Мы же подробно поговорим про allocator_traits.
allocator_traits – относительно новая сущность, которая появилась в стандарте C++11. Что она из себя представляет, как и любые traits она позволяет получать и использовать различные свойства аллокаторов – определяемые типы, вызывать методы аллокатора и пр. единым способом.
Давайте посмотрим на интерфейс, сначала типы, причем типы мы тоже разделим на несколько частей.
Сюда же относятся и типы difference_type, void_pointer и const_void_pointer, но я не стал их указывать, так как места на слайдах не очень много, но мы про них помним.
Итак, что нам говорит стандарт – первые два типа – тут все понятно, откуда взять остальные типы? У кого есть какие идеи?
На самом деле стандарт говорит следующее – если тип Allocator предоставляет нужный тип, то нужно взять его, иначе нужно взять другой тип, причем для каждого типа стандарт говорит что нужно брать.
Вот давайте разберем pointer – про него стандарт говорит следующее. Если Allocator предоставляет такой тип, то взять его. Если нет, то нужно взять указатель на Allocator::value_type.
Ну вот, давайте разберем, как это можно реализовать на примере pointer
Вообще, что касается работы с типами на этапе компиляции, то 90% случаев – это SFINAE, остальные 10% это полный перебор типов, перегрузка и пр.
Собственно, в приведенном примере я так и реализовал с помощью detail::get_pointer.
Давайте на него посмотрим
Вот так реализован шаблон get_pointer, который выбирает нужный тип в зависимости от наличия типа pointer.
Здесь приведены декларации двух шаблонных статических методов deduce_type.
Первый метод принимает на вход int и возвращает Alloc2::pointer.
Второй метод принимает на вход нечто по имени wrap_int и возвращает другой тип – указатель на value_type.
Ну и в самом низу мы декларируем тип type на основе типа возвращаемого фукнцией select_type
Итак, осталась пара вопросов, почему вторая функция select_type принимает на вход аргумент типа wrap_int и что это за аргумент?
Ну здесь на самом деле все просто, wrap_int – это структура, у которой объявлен один единственный конструктор, принимающий на вход int. Для чего это сделано – для того чтобы управлять процессом выбора перегруженной функции, в случае если обе функции подходят.
Смотрите, если наш Allocator предоставляет тип pointer, то первая функция будет определена, точно также будет определена и вторая функция. Более того, вторая функция всегда будет определена, потому что тип value_type* всегда определен – стандарт требует наличие value_type. Таким образом компилятор встает перед нелегким выбором, ему нужно выбрать одну из функций, вот он и выбирает ту, у которой входной аргумент получается явно, без неявных конверсий (и вызовов конструкторов).
Кстати, может кто нибудь сказать, как еще можно управлять процессом выбора перегруженной функции?
Ну можно вместо wrap_int воткнуть … - эллипсис. Но мы использовали wrap_int, потому что он нам пригодится в еще одном месте, там где эллипсис использовать нельзя.
Но это еще не все типы, которые нам интересны, стандарт C++11 привносит еще три типа. propagate_on_container_*.
Кто нибудь знает, для чего эти типы нужны?
Эти три типа определяют поведение контейнеров при вызове оператора копирующего присваивания, при вызове оператора перемещающего присваивания, и при вызове метода swap.
Собственно, механизм определения этих типов точно такой же как и остальных типов allocator_traits, SFINAE магия решает. Этиы типы могут принимать значения либо true_type либо false_type
Теперь, давайте разберем. Допустим propagate == true_type, тогда аллокатор участвует в операции. Это может быть нужно, если аллокатор имеет состояние (например, держит какую-то арену), тогда при копировании он может сделать новую арену, или же расшарить существующую и т.д.
Если propagate == false_type, то аллокатор не участвует в операции, это может быть полезно, если аллокатор не имеет состояния, например, зовет malloc и free. Такому аллокатору нечего копировать.
Вот методы, которые предоставляются allocator_traits, с ними ситуация аналогичная
Первые два метода обязаны предоставляться аллокатором, поэтом реализация просто их зовет.
С остальные методами ситуация следующая: если аллокатор предоставляет такие методы, то позвать их, иначе позвать стандартные реализации.
Если с первыми 4 методами все более или менее поняно, то последний метод стоит обговорить отдельно.
Итак вопрос, кто нибудь знает для чего нужен этот метод?
Этот метод используется в контейнерах при реализации копирующего конструктора. Он определяет, каким образом нам копировать аллокатор. В принципе, мы опять, можем не копировать аллокатор, а создать новый и его вернуть. Или же сделать что-то еще.
Идея реализации абсолютно аналогична выбору типов. Точно также SFINAE магия и приоритет перегруженных методово позволяет нам выбрать нужный.
Итак, с чего мы все начали, мы определяли интерфейс вектора. И уже только для того чтобы задекларировать часть публичного интерфейса вектора нам пришлось реализовать следующее подмножество std.
Я намеренно не обсуждал многие вещи, иначе мы бы до конца презентации обсуждали их, а нам надо еще реализацию вектора сделать.
Если кому интересно, я могу после доклада, в кулуарах рассказать, как реализуются те или иные сущности в стандартной библиотеке.
Мы еще не рассматривали методы вектора и пр, при рассмотрении методов еще добавится парочка сущностей.
Итак, давайте теперь перейдем к реализации нашего вектора.
Что такое vector_base, зачем я выделил его?
На самом деле все просто. Для того чтобы реализовывать вектор нужно определиться с его представлением. Как мы будем хранить начало вектора, как будем хранить размер, как будем хранить диапазон выделенной памяти?
Кроме этого в этом классе мы соберем утилитарные функции по управлению вектором.
Опять, мы рассмотрим интерфейс нашего вектора по частям.
Сначала конструкторы, операторы присваивания и деструктор.
Здесь мы, кроме всего прочего определяем и внутреннее представление вектора, мы берем три итератора – итератор на начало, на конец данных и на конец выделенной области.
Кстати, кто нибудь может сказать, зачем я здесь использую приватное наследование от аллокатора?
Это для оптимизации. Есть такая оптимизация Empty base class optimization, если базовый класс пустой, то реализация вправе не выделять под него память при наследовании. Таким образом, sizeof(vector_base) будет равен 3* sizeof(pointer) в случае, если аллокатор пустой.
Заметьте, что такого нельзя добиться если аллокатор объявить членом. Так как стандарт требует чтобы объект (даже пустой) всегда имел уникальный адрес.
Вот реализация конструкторов. Как видите она довольно простая.
Первый конструктор делегирует второму.
Второй конструктор копирует аллокатор и выставляет m_first, m_last и m_endOfCapacity в значения по умолчанию (0).
Третий конструктор – забирает у other его указатели и аллокатор.
Четвертый конструктор забирает у other указатели, и ставит новый аллокатор.
Реализация статических методов swap_base и tidy тривиальна.
В первом случае мы свопаем указатели, во втором случае мы их зануляем.
Здесь нет ничего сложного
Теперь давайте рассмотрим операторы move и copy assignment.
В принципе, они тоже довольно тривиальны.
В первом случае мы освобождаем this если он чем то владел
Затем обрабатываем аллокатор. Помните, мы обсуждали, что в allocator_traits задается стратегия как использовать аллокатор при move присваивании, вот здесь мы это обрабатываем.
Ну а дальше просто – мы свопаем this и other, а потом обнуляем other.
Оператор копирующего присваивания еще проще, в нем мы обрабатываем только аллокатор, все остальные действия будет производиться в другом месте.
Вот так реализована функция propagate_on_move_assignment
Мы диспетчеризуем вызов двум другим функциям. И в зависимости от типа мы либо муваем аллокатор, либо вообще ничего не делаем!
Точно также реализован и propagate_on_copy_assignment.
Теперь давайте опять ненадолго отвлечемся от вектора и поговорим про семейство unitialized_ функций.
На самом деле, 2 из 3-х функций вам должны быть знакомы. Они практически полностью повторяют функции std::uninitialized_copy и std::unititalized_fill_n.
Две остальные функции –unitialized_construct_a – дополнительная вспомогательная функция, котора тоже нам понадобится.
Эта функция тоже довольно проста. Мы получаем на вход итератор с неинициализированной памятью, и вызываем construct с переданными аргументами.
Как мы уже видели ранее, в реализации construct, там вызывается placement new.
Все остальные функции реализуются аналогичным образом.
Один вопрос, для чего здесь используется функция addressof?
Все очень просто – тип, по которым итерируется итератор FwdIt может иметь перегруженный оператор &, и поэтому записать &*c будет некорректно. Функция addressof как раз предназначена для получения адреса из ссылки.
Важный вопрос, какую гарантию относительно возникновения исключений дает эта функция?
Эта функция дает сильную гарантию. Если возникнет исключение, то функция оставит входной диапазон неизменным относительно начала выполнения этой функции. То есть никакого эффекта не будет.
Кстати, это касается и других функций, это очень важно, так как эти функции являются строительными кирпичиками для нашего вектора.
Итак, к чему мы пришли, у нас есть реализация базовой части вектора, которая прячет особенности реализации и предоставляет удобные обертки для дальнейшей реализации.
Что касается стандартной библиотеки, то вот несколько новых сущностей, которые мы добавили в библиотеку.
Что касается последних двух функций, то их легко получить из _a версий, просто предоставив стандартный аллокатор в качестве аргумента. И это будет удовлетворять стандарту.
Вот список константных методов – их реализация довольно проста, поэтому я не буду здесь ее приводить.
Практически все функции однострочные.
Звездочками я обозначил либо const, либо cr префиксы для функций begin и end.
Итак, нам осталось реализовать три метода вектора.
Начнем с reserve
Вот реализация функции reserve. В принципе, реализация ее довольно проста:
Проверили входные аргументы, потом выделили память для нового хранилища.
И потом позвали функцию relocate, которая переместит правильным образом наш вектор в новый регион памяти.
Кстати, теперь нас интересуют гарантии исключений для этой функции. Кто помнит, какие требования в стандарте?
Сильная гарантия – если возникнет исключение в конструкторе копирования объектов, или при выделении памяти то функция не имеет эффекта.
Если же возникнет исключение в move конструкторе, то поведение не определено. Ну это и понятно, если конструктор копирования не изменяет исходный объект, то move конструктор изменяет, и нет гарантии, что мы сможем вернуть объект в изначальное состояние.
Текущая реализация не ухудшает сильной гарантии. Остается только посмотреть на реализацию relocate.
Вот реализация функции relocate.
Как мы помним, функция uninitialized_copy предъявляет сильную гарантию, но здесь мы делаем финт. Мы делаем move_iterator из обычного итератора, таким образом, вместо копирования будет производиться перемещение, если оно доступно.
Таким образом, мы вполне легально можем переместить все объекты без копирования, что обычно дешевле.
Ну и в конце остается рутина – очистить и удалить старый регион и переназначить указатели на новое хранилище.
Вот самая интересная часть move_iterator – оператор разыменования возвращает rvalue ссылку, а не lvalue ссылку.
Таким образом, если у типа есть move конструктор или move оператор присваивания, то именно он и вызовется.
Итак, после реализации метода resever наша стандартная библиотека расширилась еще немного, и обрела реализацию иерархии исключений и реализацию basic_string!!! Что удивительно, реализация basic_string тоже использует length_error для реализации метода reserve, а конструктор length_error принимает на вход std::string, получается этакая рекурсия!!
На самом деле, я не реализовывал basic_string, вместо этого я реализовал шаблонный конструктор у length_error, который принимает любой аргумент, в том числе и строку.
Второй метод – вставка элемента или нескольких в заданную позицию
Вот я перечислил методы insert, которые должны быть реализованы.
Давайте вспомним какие требования к безопасности к ним предъявляет стандарт.
Стандарт говорит, что если вставляем один элемент в конец и он CopyInsertable или move конструктор не кидает исключений, то в случае исключения функция не имеет эффекта - строгая гарантия. Во всех остальных случаях – базовая гарантия, инварианты вектора не нарушены, состояние не определено, но валидно.
Кто может сказать, для чего в 4-й декларации используется enable_if? Чтобы различить 3 и 4 метод, например, позвали insert(pos, 0, 0). Какую функцию выбрать? Компилятор не сможет. И вот в этом случае нужен наш enable_if.
Итак, давайте посмотрим на интерфейс и подумаем, может мы сможем выразить некоторые методы через другие.
В принципе, мы 5 методов можем свести к двум.
Благодаря тому, что у нас есть perfect forwarding, то мы можем одинаково передавать любые типы ссылок. Чем мы и воспользовались здесь. То есть две реализации свелись к одной.
Вторая часть insert – вставляет диапазон.
Я здесь не стал указывать пятую реализацию, которая принимает пару итераторов. Ее реализация не менее тривиальна чем представленные здесь.
Отдельно стоит сказать про последнюю реализацию. Изначально казалось, что она ближе к первым двум, но на самом деле нет, и я сейчас объясню. Мы можем сделать специальный итератор, который просто считает свою позицию, и при разыменовании всегда возвращает один и тот же элемент.
Таким образом, мы можем сделать такой итератор и передать его в insert_range.
А вот и реализация этого counting iterator – у нас есть счетчик, текущее положение итератора, и оператор разыменования, который возвращает всегда одно и тоже значение.
Ну и операции инкремента и декремента оператора сответственно, уменьшают или увеличивают значение счетчика.
Таким образом мы получаем хитрый итератор, который всегда возвращает одно и тоже значение
Кстати, какая категория итератора может быть у этого итератора – random access iterator?
Итак, давайте рассмотрим реализацию метода
Итак, что мы делаем:
Вызываем метод grow, запрашиваем новый размер.
Потом конструируем один элемент в КОНЦЕ вектора, увеличиваем размер вектора.
Затем вызываем функцию из стандартной библиотеки rotate, которая меняет местами элементы в последовательности так, что нужный элемент оказывается на своем месте.
Ну вот и все!
Давайте посмотрим более детально.
grow – это очень простой метод, он по сути реализует стратегию роста capacity вектора. По сути он вычисляет новое значение capacity, так чтобы оно было не меньше запрашиваемого и текущего capacity, и потом зовет reserve.
Reserve как мы помним, дает строгую гарантию.
unitialized_construct_a – мы уже разбирали, он конструирует объект в памяти.
После этого мы увеличиваем размер вектора на 1.
А потом, происходит самая магия, мы вращаем элементы в векторе так, чтобы последний элемент встал на место first + offset (то есть на место нашего pos), а все последующие элементы встанут за ним в том же порядке, в котором они и были.
Вспоминаем про наши требования – вставка в конец одного элемента должна иметь строгую гарантию.
Вставка в конец элемента – это значит, что pos == end(), мы помним, что вставляем всегда перед позицией.
А это значит, что элемент уже на своем месте, и ничего вращать не надо!
Получается, что все условия соблюдены!
Единственный слайд с картинкой.
Итак, реализация алгоритма rotate довольно простая:
rotate на вход принимает 3 итератора, начало и конец, и еще один параметр – новое начало, элементы от new_firtst до end будут идти перед элементами [first, new_first).
Вот я здесь привел картинку, которая, как мне кажется поясняет работу алгоритма.
Я не буду приводить реализацию этого алгоритма, она довольно простая.
Вообще говоря, функция rotate имеет базовую гарантию, но в случае, когда ничего делать не надо – эта функция как раз ничего не делает.
Как видите, реализация метода insert_range очень похожа на реализацию предыдущего метода.
Гарантии здесь те же самые.
Кстати, кто может сказать, какое здесь сделано допущение?
Мы используем std::distance, вообще говоря, distance определена для InputIterator. Но InputIterator вообще говоря только однопроходные, то есть повторно итерироваться нельзя. Поэтому здесь надо диспетчеризировать по категории итератора.
Итак, для реализации insert нам понадобились следующие новые сущности из стандартной библиотеки.
std::rotate, которая в свою очередь зовет iter_swap
distance, для реализации метода insert_range – для подсчета расстояния между итераторами.
is_base_of, для определения категории итератора
Вот и реализация всех методов erase.
Стандарт требует только базовой гарантии для методов.
Мы опять используем фокус с rotate, чтобы ненужные элементы переместить в конец. После того как мы переместили в конец, мы зовем у них деструкторы и обновляем m_last, заметьте, capacity мы не трогали.
Итого, реализация вектора с нуля заняла у меня полторы тыщи строк. При этом я реализовал подмножество
type_traits, algorithm, utility, memory, iterator. В общем всех подсистем понемногу.
Также почти 1000 строк кода у меня заняли тесты на вектор.