Цена за 48 часов в ленте | 4100,00 |
Цена за 1 час закрепления | N/A |
Взаимопиар | Нет |
Дополнительные условия рекламы | Отсутствуют |
static_assert
, использование constexpr
, а также метапрограммирование на основе шаблонов.static_assert
позволяет проверять условия во время компиляции и генерировать ошибки, если эти условия не выполняются. Это полезно для выполнения проверок, которые должны быть гарантированы до выполнения программы.constexpr
позволяет компилятору вычислять их значения на этапе компиляции. Если функция или выражение не могут быть вычислены во время компиляции, это приведет к ошибке компиляции.static_assert
#include
// Пример с static_assert
constexpr int square(int x) {
return x * x;
}
int main() {
constexpr int value = square(5);
static_assert(value == 25, "Value must be 25"); // Проверка на этапе компиляции
// Пример с проверкой типа
static_assert(std::is_integral::value, "int must be integral type");
return 0;
}
constexpr
функций#include
constexpr int factorial(int n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}
int main() {
constexpr int result = factorial(5); // Если ошибка, компилятор сообщит об этом
static_assert(result == 120, "Factorial of 5 must be 120"); // Проверка значения
std::cout << "Factorial of 5 is " << result << std::endl;
return 0;
}
#include
// Пример метапрограммирования
template
struct Factorial {
static const int value = N * Factorial::value;
};
template<>
struct Factorial<0> {
static const int value = 1;
};
int main() {
constexpr int result = Factorial<5>::value;
static_assert(result == 120, "Factorial of 5 must be 120");
std::cout << "Factorial of 5 is " << result << std::endl;
return 0;
}
constexpr
. Функции, объявленные как constexpr
, позволяют компилятору вычислять их значения во время компиляции, если аргументы, переданные этим функциям, также являются константными выражениями. Это помогает оптимизировать код и избежать избыточных вычислений во время выполнения программы.constexpr
, может быть вычислена на этапе компиляции, если ей переданы константные выражения. Такая функция должна быть определена в том же заголовочном файле, где она объявлена.return
или блока, который может быть вычислен как константное выражение. Внутри функции можно использовать только другие constexpr
функции или константы.constexpr
также может быть использовано для объявления константных переменных, которые должны быть вычислены на этапе компиляции.#include
// Определение constexpr функции
constexpr int factorial(int n) {
return (n <= 1) ? 1 : (n * factorial(n - 1));
}
int main() {
// Вычисление значения на этапе компиляции
constexpr int result = factorial(5);
std::cout << "Factorial of 5 is " << result << std::endl; // Вывод: Factorial of 5 is 120
// Пример использования constexpr переменной
constexpr int size = 10;
int arr[size] = {0}; // Массив с размером, вычисленным на этапе компиляции
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}
std::vector
) деструкторы производного класса не будут вызываться корректно. Это может привести к утечкам памяти и другим нежелательным последствиям.std::vector
и другие контейнеры стандартной библиотеки имеют приватные и защищенные члены, к которым вы не сможете получить доступ напрямую из производного класса. Это ограничивает возможность корректного и безопасного расширения функциональности контейнера.std::vector
не обязательно является специальным типом вектора, что нарушает принцип Liskov Substitution. Лучше использовать композицию, а не наследование: создать класс, который содержит std::vector
как член и предоставляет дополнительные методы.class MyVector : public std::vector{
public:
void push_front(int value) {
this->insert(this->begin(), value); // Попытка добавить элемент в начало
}
};
int main() {
MyVector mv;
mv.push_back(1);
mv.push_back(2);
mv.push_front(0); // Вставка элемента в начало
for (const auto& elem : mv) {
std::cout << elem << " ";
}
return 0;
}
|
). Эта операция позволяет установить конкретный бит в 1, не изменяя остальные биты числа.|
) сравнивает каждый бит двух чисел. Если хотя бы один из битов в соответствующей позиции равен 1, результат в этой позиции будет 1. Иначе, результат будет 0.n
и нули в остальных позициях. Это можно сделать с помощью выражения 1 << n
.x
и маской.#include
int main() {
int x = 0b00001010; // Число, с которым работаем (10 в десятичной системе)
int n = 3; // Позиция бита, которую хотим установить (начиная с 0)
// Создаём маску с единицей в позиции n
int mask = 1 << n;
// Устанавливаем бит в позиции n
x = x | mask;
// Вывод результата
std::cout << "Результат: " << std::bitset<8>(x) << std::endl; // Двоичный вывод
std::cout << "Результат: " << x << std::endl; // Десятичный вывод
return 0;
}
1 << n
создает маску, сдвигая 1 влево на n
позиций. Например, если n = 3
, результат будет 0b00001000
. Операция x | mask
устанавливает бит в x
на позиции n
в 1. Если бит в x
на позиции n
уже был 1, он останется 1, если он был 0, то станет 1.x
было 0b00001010
и n = 3
, результат будет:0b00001000
x | mask
: 0b00001010 | 0b00001000
= 0b00001010
0b00001010
(десятичное 10).+
не определён для строковых литералов (в этом случае тип T
будет const char*
).template
T add(T a, T b) {
return a + b;
}
int main() {
std::cout << add(1, 2) << std::endl; // Работает, T = int
std::cout << add(1.5, 2.5) << std::endl; // Работает, T = double
// std::cout << add("1", "2") << std::endl; // Ошибка: компилятор не знает, как сложить строки
return 0;
}
print()
без аргументов приведёт к ошибке компиляции, так как компилятор не может определить тип T
.template
void print(T value) {
std::cout << value << std::endl;
}
int main() {
print(10); // Работает, T = int
print(3.14); // Работает, T = double
// print(); // Ошибка: компилятор не может вывести тип T
return 0;
}
template
void process(T value) {
std::cout << "Generic process: " << value << std::endl;
}
// Явная специализация для int
template <>
void process(int value) {
std::cout << "Specialized process for int: " << value << std::endl;
}
int main() {
process(10); // Использует специализированную версию для int
process(3.14); // Использует общую версию
process("text"); // Использует общую версию
return 0;
}
template
class Container {
public:
typename T::value_type getValue() {
// Здесь T::value_type должен быть известен
}
};
class MyType {
public:
using value_type = int;
};
int main() {
Containerc;
// Если MyType не содержит value_type, компиляция не удастся
return 0;
}