Я вот узнал в толькочтогодиков.
Добро пожаловать в Telegram-канал "Грокаем C++"! Здесь Вас ждут два опытных сеньора в мире программирования - Владимир и Денис, которые будут вашими гидами в изучении и погружении в этот увлекательный мир языка программирования C++.
На канале можно найти полезные советы, интересные статьи, обсуждения и многое другое, что поможет вам стать профессионалом в C++. Если у вас возникли вопросы или вы хотите получить консультацию, обращайтесь к @ninjatelegramm.
Управляющий каналом - @Spiral_Yuri, так что вы всегда можете связаться с ним, если у вас есть идеи или предложения по улучшению канала.
Для рекламы вы можете обратиться по ссылке: https://telega.in/c/grokaemcpp
Присоединяйтесь к нам и станьте частью сообщества, где ценится знание и опыт в программировании на C++! Мы также находимся на TGstat: https://tgstat.ru/channel/@grokaemcpp/stat
09 Feb, 17:09
07 Feb, 09:00
struct Queue {
void push(int value) {
storage.push_back(value);
}
void pop() {
storage.pop_front();
}
bool empty() {
return storage.empty();
}
int& front() {
return storage.front();
}
private:
std::deque<int> storage;
};
while(condition)
if (!queue.empty()) {
auto & elem = queue.front();
process_elem(elem);
queue.pop();
}
struct Queue {
void push(int value) {
std::lock_guard lg{m};
storage.push_back(value);
}
void pop() {
std::lock_guard lg{m};
storage.pop_front();
}
bool empty() {
std::lock_guard lg{m};
return storage.empty();
}
int& front() {
std::lock_guard lg{m};
return storage.front();
}
private:
std::deque<int> storage;
std::mutex m;
};
while(true)
if (!queue.empty()) {
auto & elem = queue.front();
process_elem(elem);
queue.pop();
}
struct ThreadSafeQueue {
void push(int value) {
std::lock_guard lg{m};
storage.push_back(value);
}
std::optional<int> pop() {
std::lock_guard lg{m};
if (!storage.empty()) {
int elem = storage.front();
storage.pop_front();
return elem;
}
return nullopt;
}
private:
std::deque<int> storage;
std::mutex m;
};
pop
мы можем использовать проверять и получать стейт очереди, так как мы оградились локом. Возвращаем из него std::optional
, который будет хранить фронтальный элемент, если очередь была непуста. В обратном случае он будет пуст.while(true) {
auto elem = queue.pop();
if (elem)
process_elem(elem.value());
}
06 Feb, 10:10
template<typename ... Lambdas>
struct Visitor : Lambdas...
{
Visitor(Lambdas... lambdas) : Lambdas(std::forward<Lambdas>(lambdas))... {}
using Lambdas::operator()...;
};
using var_t = std::variant<int, double, std::string>;
int main(){
std::array<var_t, 3> arr = {1.5, 42, "Hello"};
Visitor vis{[](int arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; } };
std::apply([&](auto&&... args){(std::visit(vis, std::forward<decltype(args)>(args)), ...);}, arr);
}
06 Feb, 07:07
05 Feb, 09:00
04 Feb, 07:10
01 Feb, 14:59
int count_ones(unsigned num)
{
num = (num & 0x5555555555555555 ) + ((num >> 1) & 0x5555555555555555 );
num = (num & 0x3333333333333333 ) + ((num >> 2) & 0x3333333333333333 );
num = (num & 0x0f0f0f0f0f0f0f0f ) + ((num >> 4) & 0x0f0f0f0f0f0f0f0f );
num = (num & 0x00ff00ff00ff00ff ) + ((num >> 8) & 0x00ff00ff00ff00ff );
num = (num & 0x0000ffff0000ffff ) + ((num >> 16) & 0x0000ffff0000ffff);
return num;
}
int count_ones(unsigned num) {
return std::bitset<32>{num}.count();
}
01 Feb, 14:59
int count_ones(unsigned num) {
int result = 0;
while(num > 0) {
result += num & 1;
num >>= 1;
}
return result;
}
10 = 1010
1010 & (1010 - 1) = 1010 & 1001 = 1000
118 = 111011
111011 & (111011 - 1) = 111011 & 111010 = 111010
int count_ones(unsigned num) {
int result = 0;
for(; num > 0; num &= (num - 1), ++result);
return result;
}
int count_ones(unsigned num) {
return std::popcount(num);
// or compiler extension
// return __builtin_popcount(num);
}
static std::array<uint8_t, std::numeric_limit<uint32_t>::max()> ones;
// somehow fill array
int count_ones(unsigned num) {
return ones[num];
}
int count_ones(unsigned num)
{
static unsigned char c[16]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
int count=0;
while (num)
{
count+=c[num&0x0F];
num>>=4;
}
return count;
};
31 Jan, 09:00
;
считаются разными строчками.int count_ones(unsigned num) {
// Here your code
}
28 Jan, 09:00
26 Jan, 09:00
template<typename ... Lambdas>
struct DerivedFromLambdas : Lambdas...
{
DerivedFromLambdas(Lambdas... lambdas) : Lambdas(std::forward<Lambdas>(lambdas))... {}
using Lambdas::operator()...;
};
template<typename ... Lambdas>
struct Visitor : Lambdas...
{
Visitor(Lambdas... lambdas) : Lambdas(std::forward<Lambdas>(lambdas))...
{
}
using Lambdas::operator()...;
};
using var_t = std::variant<int, double, std::string>;
int main(){
std::vector<var_t> vec = {10, 1.5, "hello"};
std::for_each(vec.begin(),
vec.end(),
[](const auto& v)
{
std::visit(Visitor{
[](int arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; } }
, v);
});
}
10 1.500000 "hello"
24 Jan, 09:00
template<class Lambda1, class Lambda2>
struct DerivedFromLambdas : public Lambda1, Lambda2
{
DerivedFromLambdas(Lambda1 lambda1, Lambda2 lambda2)
: Lambda1(std::move(lambda1))
, Lambda2{std::move(lambda2)} {}
using Lambda1::operator();
using Lambda2::operator();
};
int main(){
DerivedFromLambdas child{[](int i){return "takes int";}, [](double d){return "takes double";}};
std::cout << child(42) << std::endl;
std::cout << child(42.0) << std::endl;
return 0;
}
// OUTPUT:
// takes int
// takes double
23 Jan, 09:00
template<class Lambda>
struct DerivedFromLambda : public Lambda
{
DerivedFromLambda(Lambda lambda) : Lambda(std::move(lambda)) {}
using Lambda::operator();
};
int main(){
auto lambda = []{return 42;};
DerivedFromLambda child{lambda};
std::cout << child() << std::endl;
}
// OUTPUT:
// 42
auto lambda = []{return 42;};
DerivedFromLambda<decltype(lambda)> child{lambda};
22 Jan, 09:00
if (map_.count(token)) {
map[token]++;
} else {
map[token] = 1;
}
map[token]++;
struct CLASS {
CLASS() {std::cout << "default" << std::endl; i = 0;}
void operator++(int) {std::cout << "increment" << std::endl; i++; }
int i;
};
int main() {
std::map<std::string, CLASS> map;
map["qwe"]++;
std::cout << map["qwe"].i << std::endl;
}
default
increment
1
int();
int{};
int object{};
new int();
new int{};
std::cout << int() << std::endl;
std::cout << int{} << std::endl;
int object{};
std::cout << object << std::endl;
std::cout << *(new int()) << std::endl;
std::cout << *(new int{}) << std::endl;
0
0
0
0
0
20 Jan, 09:00
17 Jan, 09:00
std::shared_ptr<Value> IStorage::GetDataWithCache(const Key& key) {
std::unique_lock ul{mtx_};
if (auto it = cache.find(key); it != cache.end()) {
return it->second;
} else {
ul.unlock(); // HERE
std::shared_ptr<Value> result = GetData(key);
ul.lock();
cache.insert({key, result});
return result;
}
}
15 Jan, 09:00
std::shared_ptr<Value> DB::SelectWithCache(const Key& key) {
mtx_.lock();
if (auto it = cache.find(key); it != cache_.end()) {
mtx_.unlock();
return it->second;
} else {
std::shared_ptr<Value> result = Select(key);
cache.insert({key, result});
mtx_.unlock();
return result;
}
}
std::shared_ptr<Value> DB::SelectWithCache(const Key& key) {
try {
mtx_.lock();
if (auto it = cache.find(key); it != cache_.end()) {
mtx_.unlock();
return it->second;
} else {
std::shared_ptr<Value> result = Select(key);
cache.insert({key, result});
mtx_.unlock();
return result;
}
}
catch (...) {
Log("Caught an exception");
mtx_.unlock();
}
}
std::shared_ptr<Value> DB::SelectWithCache(const Key& key) {
std::lock_guard lg{mtx_};
if (auto it = cache.find(key); it != cache_.end()) {
return it->second;
} else {
std::shared_ptr<Value> result = Select(key);
cache.insert({key, result});
return result;
}
}
13 Jan, 10:00
bool MapInsertSafe(std::unordered_map<Key, Value>& map, const Key& key, Value value) {
std::lock_guard lck(mtx);
if (auto it = map.find(key))
return false;
else {
it->second = std::move(value);
return true;
}
}
void worker_thread()
{
std::unique_lock lk(m);
cv.wait(lk, []{ return ready; });
// process data
lk.unlock();
}
10 Jan, 10:00
// std::map<std::string, std::string> SomeClass::map_;
// std::mutex SomeClass::mtx_;
bool SomeClass::UpdateMap(const std::string& key, const std::string& value) {
std::lock_guard{mtx_};
auto result = map_.insert({key, value});
return result.second;
}
08 Jan, 11:00
struct Example {
int i, j;
};
Example test{1, 2};
std::cout << test.i << " " << test.j << std::endl;
// OUTPUT:
// 1 2
struct Indexes {
size_t row;
size_t col;
};
template <typename T>
struct Matrix {
Matrix() = default;
Matrix(size_t rows, size_t cols, T init)
: ROWS{rows}, COLS{cols}
, data(ROWS * COLS, init) {}
Matrix(Matrix const&) = default;
// MAGIC HERE
T& operator[](Indexes indexes) {
return data[indexes.row * COLS + indexes.col];
}
std::vector<T>& underlying_array() { return data; }
size_t row_count() const { return ROWS;}
size_t col_count() const { return COLS;}
private:
size_t ROWS;
size_t COLS;
std::vector<T> data;
};
int main() {
Matrix mtrx(4, 5, 0);
auto& interval_buffer = mtrx.underlying_array();
std::iota(interval_buffer.begin(), interval_buffer.end(), 0);
for (size_t i = 0; i < mtrx.row_count(); ++i) {
for (size_t j = 0; j < mtrx.col_count(); ++j) {
std::cout << std::setw(2) << mtrx[{i, j}] << " "; // MAGIC HERE
}
std::cout << std::endl;
}
}
struct Index {
size_t row;
};
template<typename T>
T& Matrix<T>::operator[](Index index) {
return ArraySpan{data.data() + index.row * COLS, COLS};
}
auto row = mtrx[{1}];
06 Jan, 08:10
template <typename T>
struct ArraySpan {
ArraySpan(T * arr, size_t arr_size) : data_{arr}, size_{arr_size} {}
ArraySpan(T * arr_begin, T * arr_end) : data_{arr_begin}, size_{std::distance(arr_begin, arr_end)} {}
T& operator()(std::size_t i) {
return *(data_ + i);
}
size_t size() const {return size_;}
T * data() {return data_;}
private:
T * data_;
size_t size_;
};
template <typename T>
struct Matrix {
Matrix() = default;
Matrix(size_t rows, size_t cols, T init) : ROWS{rows}, COLS{cols}, data(ROWS * COLS, init) {}
Matrix(Matrix const&) = default;
ArraySpan<T> operator()(std::size_t row) {
return ArraySpan{data.data() + row * COLS, COLS};
}
T& operator()(std::size_t row, std::size_t col) {
return data[row * COLS + col];
}
std::vector<T>& underlying_array() { return data; }
size_t row_count() const { return ROWS;}
size_t col_count() const { return COLS;}
private:
size_t ROWS;
size_t COLS;
std::vector<T> data;
};
int main() {
Matrix mtrx(4, 5, 0);
auto& interval_buffer = mtrx.underlying_array();
std::iota(interval_buffer.begin(), interval_buffer.end(), 0);
for (int i = 0; i < mtrx.row_count(); ++i) {
for (int j = 0; j < mtrx.col_count(); ++j) {
std::cout << std::setw(2) << mtrx(i, j) << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < mtrx.row_count(); ++i) {
auto row = mtrx(i);
for (int j = 0; j < row.size(); ++j) {
std::cout << std::setw(2) << row(j) << " ";
}
std::cout << std::endl;
}
}
06 Jan, 07:10
05 Jan, 09:00
template <typename T>
struct ArraySpan {
ArraySpan(T * arr, size_t arr_size) : data_{arr}, size_{arr_size} {}
ArraySpan(T * arr_begin, T * arr_end)
: data_{arr_begin}
, size_{std::distance(arr_begin, arr_end)} {}
T& operator[](std::size_t i) {
return *(data_ + i);
}
size_t size() const {return size_;}
T * data() {return data_;}
private:
T * data_;
size_t size_;
};
template <typename T>
struct Matrix {
Matrix() = default;
Matrix(size_t rows, size_t cols, T init) : ROWS{rows}, COLS{cols}, data(ROWS * COLS, init) {}
Matrix(Matrix const&) = default;
ArraySpan<T> operator[](std::size_t row) {
return ArraySpan{data.data() + row * COLS, COLS};
}
std::vector<T>& underlying_array() { return data; }
size_t row_count() const { return ROWS;}
size_t col_count() const { return COLS;}
private:
size_t ROWS;
size_t COLS;
std::vector<T> data;
};
int main() {
Matrix mtrx(4, 5, 0);
auto& interval_buffer = mtrx.underlying_array();
std::iota(interval_buffer.begin(), interval_buffer.end(), 0);
for (int i = 0; i < mtrx.row_count(); ++i) {
for (int j = 0; j < mtrx.col_count(); ++j) {
std::cout << std::setw(2) << mtrx[i][j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
for (int i = 0; i < mtrx.row_count(); ++i) {
auto row = mtrx[i];
for (int j = 0; j < row.size(); ++j) {
std::cout << std::setw(2) << row[j] << " ";
}
std::cout << std::endl;
}
}
31 Dec, 11:00
28 Dec, 10:00
void f(int *a, int b, int c)
{
a[b,c]; // deprecated
a[(b,c)]; // OK
}
26 Dec, 09:00
#include <iostream>
int main() {
auto array = new int[10, 20]{10};
std::cout << array[1, 0] << " " << array[11, 1] << std::endl;
delete[] array;
}
Expression1, Expression2, Expression3
new int[10, 20]
мы создали одномерный массив на 20 элементов.#include <iostream>
int main() {
auto array = new int[20]{10};
std::cout << array[0] << " " << array[1] << std::endl;
delete[] array;
}
10 0
.25 Dec, 09:00
#include <iostream>
int main() {
auto array = new int[10, 20]{10};
std::cout << array[1, 0] << " " << array[11, 1] << std::endl;
}
23 Dec, 09:00
std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// View data as contiguous memory representing 2 rows of 6 ints each
auto ms2 = std::mdspan(v.data(), 2, 6);
// View the same data as a 3D array 2 x 3 x 2
auto ms3 = std::mdspan(v.data(), 2, 3, 2);
// Write data using 2D view
for (std::size_t i = 0; i != ms2.extent(0); i++)
for (std::size_t j = 0; j != ms2.extent(1); j++)
ms2[i, j] = i * 1000 + j;
// Read back using 3D view
for (std::size_t i = 0; i != ms3.extent(0); i++)
{
std::println("slice @ i = {}", i);
for (std::size_t j = 0; j != ms3.extent(1); j++)
{
for (std::size_t k = 0; k != ms3.extent(2); k++)
std::print("{} ", ms3[i, j, k]);
std::println("");
}
}
slice @ i = 0
0 1
2 3
4 5
slice @ i = 1
1000 1001
1002 1003
1004 1005
23 Dec, 08:00
22 Dec, 09:00
template <typename T, std::size_t ROWS, std::size_t COLS>
class Martrix {
std::array<T, ROWS * COLS> a;
public:
Martrix() = default;
Martrix(Martrix const&) = default;
constexpr T& operator[](std::size_t row, std::size_t col) { // C++23 required
assert(row < ROWS and col < COLS);
return a[COLS * row + col];
}
constexpr std::span<T> operator[](std::size_t row) {
assert(row < ROWS);
return std::span{a.data() + row * COLS, COLS};
}
constexpr auto& underlying_array() { return a; }
};
int main() {
constexpr size_t ROWS = 4;
constexpr size_t COLS = 3;
Martrix<char, ROWS, COLS> matrix;
// fill in the underlying 1D array
auto& arr = matrix.underlying_array();
std::iota(arr.begin(), arr.end(), 'A');
for (auto row {0U}; row < ROWS; ++row) {
std::cout << "│ ";
for (auto col {0U}; col < COLS; ++col) {
std::cout << matrix[row, col] << " │ ";
}
std::cout << "\n";
}
std::cout << "\n";
auto row = matrix[1];
for (auto col {0U}; col < COLS; ++col) {
std::cout << row[col] << ' ';
}
}
│ A │ B │ C │
│ D │ E │ F │
│ G │ H │ I │
│ J │ K │ L │
D E F
21 Dec, 10:00
auto x = foo(); // копирующая инициализация
auto x{foo()}; // прямая инициализация,
// проинициализирует initializer_list (до C++17)
int x = foo(); // копирующая инициализация
int x{foo()}; // прямая инициализация
auto x1 = { 1, 2 }; // decltype(x1) - std::initializer_list<int>
auto x2 = { 1, 2.0 }; // ошибка: тип не может быть выведен,
// потому что внутри скобок объекты разных типов
auto x3{ 1, 2 }; // ошибка: не один элемент в скобках
auto x4 = { 3 }; // decltype(x4) - std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) - int
21 Dec, 07:00
20 Dec, 09:00
19 Dec, 09:00
const auto it = map_of_map_of_vectors_by_string_key.find(value);
struct MyClass {
int a = 0;
};
int main() {
MyClass x();
std::cout << x.a << std::endl;
}
auto i{0};
17 Dec, 10:00
int GetRandomNumber();
float GetRandomNumber();
int number = GetRandomNumber();
auto number = GetRandomNumber();
16 Dec, 10:00
template< class Visitor, class... Variants >
constexpr visit( Visitor&& vis, Variants&&... vars );
template< class R, class Visitor, class... Variants >
constexpr R visit( Visitor&& vis, Variants&&... vars );
using var_t = std::variant<int, long, double, std::string>;
std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
for (auto& v: vec)
{
var_t w = std::visit([](auto&& arg) -> var_t { return arg + arg; }, v);
std::visit([](auto&& arg){ std::cout << arg; }, w);
}
//OUTPUT:
// 20 30 3 hellohello
std::visit([](auto&&... arg){ ((std::cout << arg << " "),
...,
(std::cout << std::endl)); }, vec[0], vec[1]);
std::visit([](auto&&... arg){ ((std::cout << arg << " "),
...,
(std::cout << std::endl)); }, vec[0], vec[1], vec[2]);
// OUTPUT
// 10 15
// 10 15 1.5
15 Dec, 09:00
template<class T, class... Args>
void call_callback(T callback, Args... args) {
callback(args...);
}
int func() {
return 42;
}
call_callback(func);
int func() {
return 42;
}
int func(int num) {
return num;
}
call_callback(func);
call_callback(func, 42);
error: no matching function for call to
‘call_callback(<unresolved overloaded function type>)
call_callback(static_cast<int(*)()>(func));
call_callback(static_cast<int(*)(int)>(func), 42);
14 Dec, 09:11
std::transform(s.begin(), s.end(), s.begin(), std::toupper);
Let F denote a standard library function, a standard
library static member function, or an instantiation of
a standard library function template.
Unless F is designated an addressable function,
the behavior of a C++ program is unspecified
(possibly ill-formed) if it explicitly or implicitly
attempts to form a pointer to F.
Possible means of forming such pointers include
application of the unary & operator, addressof,
or a function-to-pointer standard conversion.
Moreover, the behavior of a C++ program is
unspecified (possibly ill-formed) if it attempts
to form a reference to F or if it attempts to form
a pointer-to-member designating either a standard library
non-static member function or an instantiation of
a standard library member function template.
#include <vector>
template<typename T>
void Invoke(std::vector<int>& vec, T mem_fun_ptr, int arg)
{
(vec.*mem_fun_ptr)(arg);
}
int main()
{
std::vector<int> vec;
Invoke(vec, &std::vector<int>::push_back, 42);
}
std::transform(s.begin(),
s.end(),
s.begin(),
[](unsigned char c){ return std::toupper(c); });
13 Dec, 09:00
int main()
{
std::thread thr{[]{ std::cout << "Hello, World!" << std::endl;}};
}
terminate called without an active exception
.int main()
{
std::thread thr{[]{ std::cout << "Hello, World!" << std::endl;}};
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread thr{[]{ std::cout << "Hello, World!" << std::endl;}};
thr.join();
}
int main()
{
std::jthread thr{[]{ std::cout << "Hello, World!" << std::endl;}};
}
12 Dec, 10:00
bool DBConnection::SendQuery(const char* query,
const DbQueryParams& params = DbQueryParams{});
bool DBConnection::SendQuery(const char* query,
const DbQueryParams& params = DbQueryParams{},
DbConnectionState& state);
void foo(int i, float j = 5.0, unsigned k);
foo(1, 2); // Невозможно понять, вызвали ли вы foo(1, 5.0, 2) или
например по ошибке передали слишком мало аргументов
bool DBConnection::SendQuery(const char* query,
const DbQueryParams& params = DbQueryParams{},
DbConnectionState& state = DbConnectionState::OK);
11 Dec, 09:00
10 Dec, 10:00
const std::tuple<int, char> tuple = std::make_tuple(5, 'a');
std::apply([](const auto&... elem)
{
((std::cout << elem << ' '), ..., (std::cout << std::endl));
}, tuple);
template <typename T, typename = void>
struct is_tuple_like : std::false_type {};
template <typename T>
struct is_tuple_like<T, std::void_t<decltype(std::tuple_size<T>::value), decltype(std::get<0>(std::declval<T>()))>> : std::true_type {};
template <typename T>
constexpr bool is_tuple_like_v = is_tuple_like<T>::value;
template<typename Tval, typename ... T>
void serialize_tuple_like(std::stringstream &outbuf, const Tval& arg, const T& ... rest) noexcept {
if constexpr (is_tuple_like_v<Tval>){
outbuf << "{ ";
std::apply([&outbuf](auto const&... packed_values) {
serialize_tuple_like(outbuf, packed_values ...);
}, arg);
outbuf << " }";
}
else{
outbuf << arg;
}
if constexpr(sizeof...(rest) > 0){
outbuf << ' ';
serialize_tuple_like(outbuf, rest ...);
}
}
template<typename ... T>
std::string args_to_string(const T& ... args) noexcept {
std::stringstream outbuf{};
if constexpr(sizeof...(args) > 0){
serialize_tuple_like(outbuf, args ...);
}
return outbuf.str();
}
int main(){
std::cout << args_to_string("test", 1,
std::tuple{"tuple1", 2, 3.0,
std::tuple{"tuple2", "boom"}},
std::pair{"pair", 4},
std::array{5, 6, 7, 8, 9});
}
test 1 { tuple1 2 3 { tuple2 boom } } { pair 4 } { 5 6 7 8 9 }
09 Dec, 08:28
08 Dec, 09:18
void Foo::bar(Foo * const this, Type1 param1, Type2 param2) {}
void Foo::change(Foo *foo) { this = foo; }
void Foo::ConstMemberFunction(Type1 param1, Type2 param2) const {
// this - const Foo *
this->field = param1; // Error!
}
07 Dec, 09:00
std::map<std::string, std::string> map;
std::string get_value(const std::string& key) {
if (!map.contains(key)) {
std::string value = longCalculations(key);
map[key] = value;
return value;
} else {
return map[key];
}
}
std::string get_value(const std::string& key) {
auto it = map.find(key);
if (it == map.end()) {
std::string value = longCalculations(key);
map[key] = value;
return value;
} else {
return it->second;
}
}
std::set<std::string> tokens;
std::string json_token;
Json json;
if (tokens.contains(json_token)) {
transformJson(json, json_token);
}
06 Dec, 09:00
if (map.count(key)) {
// do something
}
contains
. Он проверяет, если ли в контейнере элементы с данным ключом. Теперь код выглядит так:if (map.contains(key)) {
// do something
}
05 Dec, 09:00
int number = 42;
int * p_num = &number;
template< class T >
T* addressof( T& arg ) noexcept;
template< class T >
const T* addressof( const T&& ) = delete;
template<class T>
struct Ptr
{
T* pad; // add pad to show difference between 'this' and 'data'
T* data;
Ptr(T* arg) : pad(nullptr), data(arg)
{
std::cout << "Ctor this = " << this << '\n';
}
~Ptr() { delete data; }
T** operator&() { return &data; }
};
template<class T>
void f(Ptr<T>* p)
{
std::cout << "Ptr overload called with p = " << p << '\n';
}
void f(int** p)
{
std::cout << "int** overload called with p = " << p << '\n';
}
int main()
{
Ptr<int> p(new int(42));
f(&p); // calls int** overload
f(std::addressof(p)); // calls Ptr<int>* overload, (= this)
}
// OUTPUT
// Ctor this = 0x7fff59ae6e88
// int** overload called with p = 0x7fff59ae6e90
// Ptr overload called with p = 0x7fff59ae6e88
03 Dec, 09:00
02 Dec, 10:05
Certain sets of names and function signatures
are always reserved to the implementation:
- Each name that contains a double underscore (__) or
begins with an underscore followed by an uppercase letter
is reserved to the implementation for any use.
- Each name that begins with an underscore is reserved
to the implementation for use as a name in the global namespace.
Such names are also reserved in namespace ::std (17.4.3.1).
02 Dec, 07:01
01 Dec, 10:00
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
}
30 Nov, 09:00
class MyClass
{
int m_foo;
int m_bar;
public:
int addAll() const;
int getFoo() const;
void setFoo(int foo);
int getBar() const;
void setBar(int bar);
};
int MyClass::addAll() const
{
return m_foo + m_bar;
}
int MyClass::getFoo() const
{
return m_foo;
}
void MyClass::setFoo(int foo)
{
m_foo = foo;
}
int MyClass::getBar() const
{
return m_bar;
}
void MyClass::setBar(int bar)
{
m_bar = bar;
}
struct MyClass
{
int m_foo;
int m_bar;
}
29 Nov, 10:00
28 Nov, 10:00
struct Task {
void Execute() {
// pretend that this is very long calculations
std::this_thread::sleep_for(std::chrono::seconds(2));
}
};
void WorkingThread(std::deque<Task> queue) {
std::mutex mtx;
mtx.lock();
while (!queue.empty()) {
auto elem = queue.front();
queue.pop_front();
elem.Execute();
lck.unlock();
// to get other threads opportunity to work
std::this_thread::sleep_for(std::chrono::milliseconds(1));
lck.lock();
}
}
int main() {
std::deque<Task> queue(10);
std::thread thr1{WorkingThread, queue}, thr2{WorkingThread, queue};
}
26 Nov, 10:00
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("Running main with argc = %d, last = '%s'\n",
argc, argv[argc-1]);
if (argc > 1)
return main(argc - 1, argv);
return 0;
}
Running main with argc = 4, last = '3'
Running main with argc = 3, last = '2'
Running main with argc = 2, last = '1'
Running main with argc = 1, last = './recursive_main'
26 Nov, 07:00
25 Nov, 08:00
template< class Lockable1, class Lockable2, class... LockableN >
int try_lock( Lockable1& lock1, Lockable2& lock2, LockableN&... lockn );
23 Nov, 09:39
1 поток | 2 поток |
-------------------------------|---------------------------------|
lock(mutex2) // УСПЕШНО | |
| scoped_lock() |
| lock(mutex1) // УСПЕШНО |
| lock(mutex2) // ОЖИДАНИЕ ... |
lock(mutex1) // ОЖИДАНИЕ... | |
std::mutex l1, l2, l3, l4;
// Пусть я как-то гарантирую, что они пронумерованы в порядке
возрастания адресов и std::scoped_lock(sc_lock для краткости)
работает с помощью сортировки по адресам
1 поток | 2 поток | 3 поток | 4 поток
-------------|----------------|----------------|----------------
l4.lock(); | | |
//blocks here| | |
|sc_lock(l3, l4);| |
| // lock l3 | |
| // blocks on l4| |
|sc_lock(l2, l3);|
| // lock l2 |
| // blocks on l3|
| | sc_lock(l1, l2);
| // lock l1
| // blocks on l2
21 Nov, 08:00
20 Nov, 09:28
19 Nov, 09:00
18 Nov, 09:00
struct SomeSharedResource {
void swap(SomeSharedResource& obj) {
{
// !!!
std::unique_lock<std::mutex> lk_c1(mtx, std::defer_lock);
std::unique_lock<std::mutex> lk_c2(obj.mtx, std::defer_lock);
std::lock(mtx, obj.mtx);
// handle swap
}
}
std::mutex mtx;
};
int main() {
SomeSharedResource resource1;
SomeSharedResource resource2;
std::mutex m2;
std::thread t1([&resource1, &resource2] {
resource1.swap(resource2);
std::cout << "1 Do some work" << std::endl;
});
std::thread t2([&resource1, &resource2] {
resource2.swap(resource1);
std::cout << "2 Do some work" << std::endl;
});
t1.join();
t2.join();
}
struct SomeSharedResource {
void swap(SomeSharedResource& obj) {
{
// !!!
std::lock(mtx, obj.mtx);
std::lock_guard<std::mutex> lk_c1(mtx, std::adopt_lock);
std::lock_guard<std::mutex> lk_c2(obj.mtx, std::adopt_lock);
// handle swap
}
}
std::mutex mtx;
};
17 Nov, 11:00
struct SomeSharedResource {
void swap(SomeSharedResource& obj) {
{
std::scoped_lock lg{mtx, obj.mtx};
// handle swap
}
}
std::mutex mtx;
};
int main() {
SomeSharedResource resource1;
SomeSharedResource resource2;
std::mutex m2;
std::thread t1([&resource1, &resource2] {
resource1.swap(resource2);
std::cout << "1 Do some work" << std::endl;
});
std::thread t2([&resource1, &resource2] {
resource2.swap(resource1);
std::cout << "2 Do some work" << std::endl;
});
t1.join();
t2.join();
}
15 Nov, 11:00
struct SomeSharedResource {
void swap(SomeSharedResource& obj) {
{
std::lock_guard lg{mtx};
// just for results reproducing
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::lock_guard lg1{obj.mtx};
// handle swap
}
}
std::mutex mtx;
};
int main() {
SomeSharedResource resource1;
SomeSharedResource resource2;
std::mutex m2;
std::thread t1([&resource1, &resource2] {
resource1.swap(resource2);
std::cout << "1 Do some work" << std::endl;
});
std::thread t2([&resource1, &resource2] {
resource2.swap(resource1);
std::cout << "2 Do some work" << std::endl;
});
t1.join();
t2.join();
}
15 Nov, 07:01
13 Nov, 11:00
std::mutex m1;
std::mutex m2;
std::thread t1([&m1, &m2] {
std::cout << "Thread 1. Acquiring m1." << std::endl;
m1.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "Thread 1. Acquiring m2." << std::endl;
m2.lock();
std::cout << "Thread 1 perform some work" << std::endl;
});
std::thread t2([&m1, &m2] {
std::cout << "Thread 2. Acquiring m2." << std::endl;
m2.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::cout << "Thread 2. Acquiring m1." << std::endl;
m1.lock();
std::cout << "Thread 2 perform some work" << std::endl;
});
t1.join();
t2.join();
Thread 1. Acquiring m1.
Thread 2. Acquiring m2.
Thread 2. Acquiring m1.
Thread 1. Acquiring m2.
13 Nov, 08:00
12 Nov, 12:04
std::optional<std::reference_wrapper<T>> Container::front() {
if (data_.empty()) {
return std::nullopt;
}
return std::ref(data_[0]);
}
11 Nov, 09:00
09 Nov, 12:01
struct Person {
Person(const std::string &first_name,
const std::string &last_name) : first_name_{first_name},
last_name_{last_name} {}
friend std::ostream& operator<<(std::ostream& o, const Person& b) {
return o << b.to_str();
}
protected:
virtual std::string to_str() const{
return first_name_ + " " + last_name_;
}
private:
std::string first_name_;
std::string last_name_;
};
struct TaxPayer : Person {
TaxPayer(const std::string first_name,
const std::string last_name,
const std::string itn) : Person{first_name, last_name}, itn_{itn} {}
protected:
virtual std::string to_str() const{
return Person::to_str() + " " + itn_;
}
private:
std::string itn_;
};
int main() {
auto prs1 = std::make_unique<Person>("Ter", "Minator");
auto prs2 = std::make_unique<TaxPayer>("Ace", "Ventura", "0000");
std::cout << *prs1 << std::endl;
std::cout << *prs2 << std::endl;
}
// OUTPUT:
// Ter Minator
// Ace Ventura 0000
08 Nov, 09:00
08 Nov, 08:00
05 Nov, 09:00
++value
.value++
.возвращаемое_значение operator{символы_вызова_оператора}(аргументы)
.возвращаемое_значение
ссылку на объект, на место символы_вызова_оператора
подставляем =, на место аргументов - const Type&. Получается так:Type& operator=(const Type&);
Type& operator++() {
value_ += 1;
return *this;
}
Type operator++() {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}
functions that differ only in their return type cannot be overloaded
.Type operator++(int) {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}
struct Type {
Type& operator++() {
value_ += 1;
return *this;
}
Type operator++(int) {
auto tmp_value = *this;
value_ += 1;
return tmp_value;
}
private:
IntegerLikeType value_;
};
04 Nov, 09:00
auto u_ptr = std::make_unique<Type>();
std::cout << u_ptr.get() << std::endl;
auto u_ptr = std::make_unique<Type>();
std::cout << u_ptr << std::endl;
03 Nov, 09:00
static int dummy = (some_function(), 0);
int main() {}
01 Nov, 15:00
#include <iostream>
#include <random>
int a;
int b;
int main() {
a = rand();
b = rand();
std::cout << (a + b);
}
a:
.zero 4
b:
.zero 4
main:
push rbp
mov rbp, rsp
call rand
...
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
mov eax, 0
pop rbp
ret
31 Oct, 09:00
Because the explicit template argument list follows the function template name,
and because constructor templates are named without using a function name,
there is no way to provide an explicit template argument list for these function templates.
struct Type {
template <typename>
Type() {}
};
struct Type {
template <typename>
Type() {};
};
struct Other {};
int main() {
Type t = std::bit_cast<Type>(Other{});
}
30 Oct, 10:00
struct Type {
template <typename>
Type() {}
};
28 Oct, 08:10
extern std::ostream cout;
extern std::istream cin;
...
// Standard stream objects.
// NB: Iff <iostream> is included, these definitions become wonky.
typedef char fake_istream[sizeof(istream)]
attribute ((aligned(alignof(istream))));
typedef char fake_ostream[sizeof(ostream)]
attribute ((aligned(alignof(ostream))));
fake_istream cin;
fake_ostream cout;
fake_ostream cerr;
fake_ostream clog;
// header.hpp
#pragma once
struct TwoFields {
int a;
int b;
};
struct ThreeFields {
char a;
int b;
long long c;
};
// source.cpp
ThreeFields test = {1, 2, 3};
// main.cpp
#include <iostream>
#include "header.hpp"
extern TwoFields test;
int main() {
std::cout << test.a << " " << test.b << std::endl;
}
28 Oct, 06:10
27 Oct, 15:00
std::cout << "Print something in consol\n";
std::ostream& operator<< (std::ostream& stream, const char * str)
extern istream cin; ///< Linked to standard input
extern ostream cout; ///< Linked to standard output
extern ostream cerr; ///< Linked to standard error (unbuffered)
extern ostream clog; ///< Linked to standard error (buffered)
...
static ios_base::Init __ioinit;
ios_base::Init::Init()
{
if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1) == 0)
{
// Standard streams default to synced with "C" operations.
_S_synced_with_stdio = true;
new (&buf_cout_sync) stdio_sync_filebuf<char>(stdout);
new (&buf_cin_sync) stdio_sync_filebuf<char>(stdin);
new (&buf_cerr_sync) stdio_sync_filebuf<char>(stderr);
// The standard streams are constructed once only and never
// destroyed.
new (&cout) ostream(&buf_cout_sync);
new (&cin) istream(&buf_cin_sync);
new (&cerr) ostream(&buf_cerr_sync);
new (&clog) ostream(&buf_cerr_sync);
cin.tie(&cout);
cerr.setf(ios_base::unitbuf);
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 455. cerr::tie() and wcerr::tie() are overspecified.
cerr.tie(&cout);
...
__gnu_cxx::__atomic_add_dispatch(&_S_refcount, 1);
// Standard stream objects.
// NB: Iff <iostream> is included, these definitions become wonky.
typedef char fake_istream[sizeof(istream)]
attribute ((aligned(alignof(istream))));
typedef char fake_ostream[sizeof(ostream)]
attribute ((aligned(alignof(ostream))));
fake_istream cin;
fake_ostream cout;
fake_ostream cerr;
fake_ostream clog;
26 Oct, 10:06
#include <iostream>
int my_fun();
void _start()
{
int x = my_fun();
exit(x);
}
int my_fun()
{
std::cout << "Hello, World!\n";
return 0;
}
Hello, World!
24 Oct, 17:12
void fun1() {
int initialize = 10;
std::cout << initialize << std::endl;
}
void fun2() {
int uninitialize;
std::cout << uninitialize << std::endl;
}
int main() {
fun2();
fun1();
fun2();
}
32760
10
10
23 Oct, 09:00
22 Oct, 09:00
int i;
FillUpVariable(i);
21 Oct, 12:00
#include <iostream>
int id;
int main()
{
std::cout << id;
}
21 Oct, 10:01
20 Oct, 09:00
18 Oct, 09:09
std::pair<std::string, int> pair{"Hello there!", 1};
std::pair pair{"Hello there!", 1};
size_t size = pair.first.size();
error: request for member 'size' in 'a.std::pair<const char*, int>::first',
which is of non-class type 'const char*'
std::pair pair{std::string("Hello there!"), 1};
17 Oct, 09:00
16 Oct, 09:00
void pop_back();
void pop_front();
bool pop_back() {
if (data_.empty()) {
return false;
}
// remove element
return true;
}
15 Oct, 10:00
int main() {
while(1);
return 0;
}
void unreachable() {
std::cout << "Hello, World!" << std::endl;
}
main:
// Perform some code
ret
main:
unreachable():
push rax
mov rdi, qword ptr [rip + std::cout@GOTPCREL]
lea rsi, [rip + .L.str]
call std::basic_ostream<char, std::char_traits<char>>...
13 Oct, 10:00
void foo(int /no name here/);
void foo(int /no name here/)
{
std::cout << "foo" << std::endl;
}
foo(5);
struct Digit
{
Digit(int digit=0) : m_digit{digit} {}
Digit& operator++(); // prefix has no parameter
Digit operator++(int); // postfix has an int parameter
private:
int m_digit{};
};
11 Oct, 10:08
void RunSomeThread(const & SomeType obj) {...}
std::thread thr(RunSomeThread, obj);
std::thread thr(RunFuckingThread, std::ref(obj));
10 Oct, 09:00
09 Oct, 10:00
std::map<int, int> map{{1, 6}, {2, 7}, {3, 8}, {4, 9}, {5, 10}};
// вот так
auto it = std::find_if(map.begin(), map.end(), [](const auto& elem) {return elem.second == 10;});
map.erase(it);
//
std::for_each(map.begin(), map.end(), [](const auto& item){
std::cout << item.first << " " << item.second << std::endl;});
// OUTPUT
// 1 6
// 2 7
// 3 8
// 4 9
std::erase_if(map, [](const auto& elem) {return elem.second == 10;});
#include <experimental/map>
std::experimental::erase_if(map, [](const auto& elem) {return elem.second == 10;});
08 Oct, 09:00
07 Oct, 09:00
06 Oct, 11:00
04 Oct, 09:09
03 Oct, 09:00
int add(int lhs, int rhs) {
int sum;
if (__builtin_add_overflow(lhs, rhs, &sum))
abort();
return sum;
}
mov %edi, %eax
add %esi, %eax
jo call_abort
ret
call_abort:
call abort
jo
. Это условный прыжок. Если условие истино - прыгаем на метку call_abort, если нет - то выходим из функции.jo
выполняет прыжок, если выставлен флаг OF в регистре EFLAGS. То есть Overflow Flag. Он выставляется в двух случаях:02 Oct, 09:00
bool __builtin_add_overflow(type1 a, type2 b, type3 *res);
bool __builtin_sub_overflow(type1 a, type2 b, type3 *res);
bool __builtin_mul_overflow(type1 a, type2 b, type3 *res);
std::optional<int32_t> decimal_reverse(int32_t value) {
int32_t result{};
while (value) {
if (__builtin_mul_overflow(result, 10, &result) or
__builtin_add_overflow(result, value % 10, &result))
return std::nullopt;
value /= 10;
}
return result;
}
int main() {
if (decimal_reverse(1234567891).has_value()) {
std::cout << decimal_reverse(1234567891).value() << std::endl;
} else {
std::cout << "Reversing cannot be perform due overflow" << std::endl;
}
if (decimal_reverse(1234567894).has_value()) {
std::cout << decimal_reverse(1234567894).value() << std::endl;
} else {
std::cout << "Reversing cannot be perform due overflow" << std::endl;
}
}
// OUTPUT:
// 1987654321
// Reversing cannot be perform due overflow
01 Oct, 09:16
000...00
, один как 000...01
и тд. Максимальное значение этого типа INT_MAX выглядит так: 0111...11 (2,147,483,647). Но! Когда мы прибавляем к нему единичку, то получаем 100...000
, что переворачиваем знаковый бит, число становится отрицательным и равным INT_MIN.28 Sep, 09:00