add primary container and concepts for logger
This commit is contained in:
@@ -66,13 +66,6 @@ void example_is_sequence_container(const T& container)
|
|||||||
hack::log()("Sequence container with ", container.size(), " elements");
|
hack::log()("Sequence container with ", container.size(), " elements");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<hack::concepts::is_random_access_container T>
|
|
||||||
void example_is_random_access_container(T& container)
|
|
||||||
{
|
|
||||||
if (!container.empty())
|
|
||||||
hack::log()("First element: ", container[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<hack::concepts::is_container_adapter T>
|
template<hack::concepts::is_container_adapter T>
|
||||||
void example_is_container_adapter(T& adapter)
|
void example_is_container_adapter(T& adapter)
|
||||||
{
|
{
|
||||||
@@ -139,15 +132,6 @@ void check_support(const T& value)
|
|||||||
hack::log()("Type is supported");
|
hack::log()("Type is supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<hack::concepts::has_key_value_semantics T>
|
|
||||||
void example_has_key_value_semantics(T& container)
|
|
||||||
{
|
|
||||||
if constexpr (hack::concepts::has_mapped_type<T>)
|
|
||||||
hack::log()("Key-value container, sample access demonstrated");
|
|
||||||
else
|
|
||||||
hack::log()("Set-like container");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<hack::concepts::is_contiguous_container T>
|
template<hack::concepts::is_contiguous_container T>
|
||||||
void example_is_contiguous_container(const T& container)
|
void example_is_contiguous_container(const T& container)
|
||||||
{
|
{
|
||||||
@@ -210,9 +194,7 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
example_is_string(str);
|
example_is_string(str);
|
||||||
example_is_sequence_container(vec);
|
example_is_sequence_container(vec);
|
||||||
example_is_sequence_container(list);
|
example_is_sequence_container(list);
|
||||||
example_is_random_access_container(vec);
|
|
||||||
example_is_container_adapter(stack);
|
example_is_container_adapter(stack);
|
||||||
example_is_associative_container(set);
|
|
||||||
example_is_unordered_associative_container(umap);
|
example_is_unordered_associative_container(umap);
|
||||||
example_is_tuple_like(tuple);
|
example_is_tuple_like(tuple);
|
||||||
example_is_fixed_array(fixed_array);
|
example_is_fixed_array(fixed_array);
|
||||||
@@ -222,7 +204,6 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
example_is_sized(vec);
|
example_is_sized(vec);
|
||||||
check_support(a);
|
check_support(a);
|
||||||
check_support(custom);
|
check_support(custom);
|
||||||
example_has_key_value_semantics(map);
|
|
||||||
example_is_contiguous_container(vec);
|
example_is_contiguous_container(vec);
|
||||||
example_can_push_front(list, 0);
|
example_can_push_front(list, 0);
|
||||||
example_can_push_back(vec, 99);
|
example_can_push_back(vec, 99);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "hack/logger/logger.hpp"
|
#include "hack/logger/logger.hpp"
|
||||||
|
|
||||||
@@ -9,15 +11,48 @@ auto main(int argc, char *argv[]) -> int
|
|||||||
double d = 2.0;
|
double d = 2.0;
|
||||||
float f = 3.f;
|
float f = 3.f;
|
||||||
std::vector<std::string> vs = { "a", "b", "c" };
|
std::vector<std::string> vs = { "a", "b", "c" };
|
||||||
|
std::list<int> l = { 1, 2, 3 };
|
||||||
|
std::deque<float> df = { 1.1f, 2.1f, 3.1f };
|
||||||
|
std::forward_list<int> fl = { 1, 2, 3 };
|
||||||
std::map<int, int> mi = { { 1, 1 }, { 2, 2 }, { 3, 3 } };
|
std::map<int, int> mi = { { 1, 1 }, { 2, 2 }, { 3, 3 } };
|
||||||
|
std::multimap<int, int> mmi = { { 1, 1 }, { 1, 1 }, { 2, 2 }, { 3, 3 } };
|
||||||
|
std::unordered_map<int, int> umi = { { 1, 1 }, { 1, 1 }, { 2, 2 }, { 3, 3 } };
|
||||||
|
std::tuple<int, std::string, bool> tp = { 1, "asdf", false };
|
||||||
|
std::stack<int> sti;
|
||||||
|
sti.push(1);
|
||||||
|
sti.push(2);
|
||||||
|
sti.push(3);
|
||||||
|
std::set<int> si = { 1, 2, 3 };
|
||||||
|
std::unordered_set<int> usi = { 1, 1, 1 };
|
||||||
|
|
||||||
hack::log().set_devider(", ");
|
hack::log().set_devider(", ");
|
||||||
hack::log().no_func();
|
hack::log().no_func();
|
||||||
hack::log()(1, 2, 3.1f, 4.3, "asdf", "qwer", "xzcv");
|
hack::log()(1, i, 3.1f, f, 4.3, d, "asdf");
|
||||||
hack::log().set_devider(" = ");
|
hack::log().set_devider(" = ");
|
||||||
hack::log()(1, 2, 3.1f, 4.3, "asdf", "qwer", "xzcv");
|
hack::log()(1, i, 3.1f, f, 4.3, d, "asdf");
|
||||||
hack::log().reset();
|
hack::log().reset();
|
||||||
hack::log()(1, 2, 3.1f, 4.3, "asdf", "qwer", "xzcv");
|
hack::log()(1, i, 3.1f, f, 4.3, d, "asdf");
|
||||||
|
hack::log().set_devider(", ");
|
||||||
|
hack::log().no_func();
|
||||||
|
hack::log().no_file();
|
||||||
|
hack::log().no_row();
|
||||||
|
hack::log()(vs);
|
||||||
|
hack::log()(l);
|
||||||
|
hack::log()(df);
|
||||||
|
hack::log()(fl);
|
||||||
|
hack::log().reset();
|
||||||
|
hack::log()(mi);
|
||||||
|
hack::log()(mmi);
|
||||||
|
hack::log()(umi);
|
||||||
|
hack::log()(tp);
|
||||||
|
hack::log()(true);
|
||||||
|
hack::log().bool_as_number();
|
||||||
|
hack::log()(true);
|
||||||
|
hack::log()(si);
|
||||||
|
hack::log()(usi);
|
||||||
|
hack::log().reset();
|
||||||
|
hack::log().set_devider(", ");
|
||||||
|
hack::log()(sti, 123, true);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@@ -91,16 +89,6 @@ namespace hack::concepts
|
|||||||
std::same_as<T, std::deque<typename T::value_type, typename T::allocator_type>> ||
|
std::same_as<T, std::deque<typename T::value_type, typename T::allocator_type>> ||
|
||||||
std::same_as<T, std::forward_list<typename T::value_type, typename T::allocator_type>>);
|
std::same_as<T, std::forward_list<typename T::value_type, typename T::allocator_type>>);
|
||||||
|
|
||||||
// Контейнеры с произвольным доступом
|
|
||||||
// @brief Проверяет, поддерживает ли контейнер произвольный доступ
|
|
||||||
// @details Обнаруживает контейнеры с оператором [] для быстрого доступа:
|
|
||||||
// - std::vector - O(1) доступ по индексу
|
|
||||||
// - std::deque - O(1) доступ по индексу
|
|
||||||
// - std::array - фиксированный массив с быстрым доступом
|
|
||||||
// Важно для алгоритмов, требующих частого доступа к элементам по индексу
|
|
||||||
template<typename T>
|
|
||||||
concept is_random_access_container = is_sequence_container<T> && requires(T t, std::size_t idx) { t[idx]; };
|
|
||||||
|
|
||||||
// Адаптеры контейнеров
|
// Адаптеры контейнеров
|
||||||
// @brief Проверяет, является ли тип адаптером контейнера
|
// @brief Проверяет, является ли тип адаптером контейнера
|
||||||
// @details Обнаруживает типы-обертки над другими контейнерами:
|
// @details Обнаруживает типы-обертки над другими контейнерами:
|
||||||
@@ -118,32 +106,24 @@ namespace hack::concepts
|
|||||||
// @details Обнаруживает контейнеры, хранящие элементы в отсортированном порядке:
|
// @details Обнаруживает контейнеры, хранящие элементы в отсортированном порядке:
|
||||||
// - std::map - словарь с уникальными ключами
|
// - std::map - словарь с уникальными ключами
|
||||||
// - std::multimap - словарь с возможностью дубликатов ключей
|
// - std::multimap - словарь с возможностью дубликатов ключей
|
||||||
// - std::set - множество уникальных элементов
|
|
||||||
// - std::multiset - множество с возможностью дубликатов
|
|
||||||
// Использует key_compare для упорядочивания (обычно std::less)
|
// Использует key_compare для упорядочивания (обычно std::less)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept is_associative_container = has_iterator<T> &&
|
concept is_associative_container = has_iterator<T> &&
|
||||||
has_key_type<T> &&
|
has_key_type<T> &&
|
||||||
(has_mapped_type<T> || !has_mapped_type<T>) && // Для map и set
|
(has_mapped_type<T> || !has_mapped_type<T>) && // Для map и set
|
||||||
(std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
|
(std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
|
||||||
std::same_as<T, std::multimap<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
|
std::same_as<T, std::multimap<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>>);
|
||||||
std::same_as<T, std::set<typename T::key_type, typename T::key_compare, typename T::allocator_type>> ||
|
|
||||||
std::same_as<T, std::multiset<typename T::key_type, typename T::key_compare, typename T::allocator_type>>);
|
|
||||||
|
|
||||||
// Неупорядоченные ассоциативные контейнеры
|
// Неупорядоченные ассоциативные контейнеры
|
||||||
// @brief Проверяет, является ли тип неупорядоченным ассоциативным контейнером
|
// @brief Проверяет, является ли тип неупорядоченным ассоциативным контейнером
|
||||||
// @details Обнаруживает контейнеры, использующие хеширование:
|
// @details Обнаруживает контейнеры, использующие хеширование:
|
||||||
// - std::unordered_map - хеш-таблица с уникальными ключами
|
// - std::unordered_map - хеш-таблица с уникальными ключами
|
||||||
// - std::unordered_multimap - хеш-таблица с дубликатами ключей
|
// - std::unordered_multimap - хеш-таблица с дубликатами ключей
|
||||||
// - std::unordered_set - хеш-множество уникальных элементов
|
|
||||||
// - std::unordered_multiset - хеш-множество с дубликатами
|
|
||||||
// Используют хеш-функции и сравнение на равенство вместо упорядочивания
|
// Используют хеш-функции и сравнение на равенство вместо упорядочивания
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept is_unordered_associative_container = has_iterator<T> && has_key_type<T> && (has_mapped_type<T> || !has_mapped_type<T>) &&
|
concept is_unordered_associative_container = has_iterator<T> && has_key_type<T> && (has_mapped_type<T> || !has_mapped_type<T>) &&
|
||||||
(std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>> ||
|
(std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>> ||
|
||||||
std::same_as<T, std::unordered_multimap<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>> ||
|
std::same_as<T, std::unordered_multimap<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>);
|
||||||
std::same_as<T, std::unordered_set<typename T::key_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>> ||
|
|
||||||
std::same_as<T, std::unordered_multiset<typename T::key_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>);
|
|
||||||
|
|
||||||
// Кортежи и пары
|
// Кортежи и пары
|
||||||
// @brief Проверяет, является ли тип кортежоподобным
|
// @brief Проверяет, является ли тип кортежоподобным
|
||||||
@@ -225,17 +205,6 @@ namespace hack::concepts
|
|||||||
is_tuple_like<T> ||
|
is_tuple_like<T> ||
|
||||||
std::is_pointer_v<T>);
|
std::is_pointer_v<T>);
|
||||||
|
|
||||||
// Вспомогательные концепты для метапрограммирования
|
|
||||||
// @brief Проверяет, имеет ли тип семантику ключ-значение
|
|
||||||
// @details Обнаруживает контейнеры, которые поддерживают доступ по ключу:
|
|
||||||
// - map и unordered_map (operator[])
|
|
||||||
// - set и unordered_set (хотя у set нет разделения на key/value)
|
|
||||||
// Полезно для алгоритмов работы со словарями и ассоциативными массивами
|
|
||||||
template<typename T>
|
|
||||||
concept has_key_value_semantics = is_associative_container<T> ||
|
|
||||||
is_unordered_associative_container<T> ||
|
|
||||||
requires(T t, typename T::key_type key) { t[key]; };
|
|
||||||
|
|
||||||
// @brief Проверяет, является ли тип контейнером с непрерывной памятью
|
// @brief Проверяет, является ли тип контейнером с непрерывной памятью
|
||||||
// @details Обнаруживает контейнеры, элементы которых хранятся в непрерывной памяти:
|
// @details Обнаруживает контейнеры, элементы которых хранятся в непрерывной памяти:
|
||||||
// - std::vector - динамический массив
|
// - std::vector - динамический массив
|
||||||
@@ -268,15 +237,87 @@ namespace hack::concepts
|
|||||||
template<typename Container, typename Key>
|
template<typename Container, typename Key>
|
||||||
concept can_find = requires(Container c, Key&& key) { c.find(std::forward<Key>(key)); };
|
concept can_find = requires(Container c, Key&& key) { c.find(std::forward<Key>(key)); };
|
||||||
|
|
||||||
|
// @brief Проверяет, является ли тип bool
|
||||||
|
template<typename T>
|
||||||
|
concept is_bool = std::is_same_v<std::remove_cvref_t<T>, bool>;
|
||||||
|
|
||||||
// @brief Проверяет, является ли данное числом
|
// @brief Проверяет, является ли данное числом
|
||||||
// @details Проверяет на основные операции
|
// @details Проверяет на основные операции
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept is_number = requires(T value) {
|
concept is_number = requires(T value) {
|
||||||
requires std::is_arithmetic_v<T>; // Включает все арифметические типы
|
requires std::is_arithmetic_v<T> && !is_bool<T>; // Включает все арифметические типы
|
||||||
value + value; // Проверяет арифметические операции
|
value + value; // Проверяет арифметические операции
|
||||||
value - value;
|
value - value;
|
||||||
value * value;
|
value * value;
|
||||||
value / value;
|
value / value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept is_set_like = requires {
|
||||||
|
// Общие требования для всех set-like контейнеров
|
||||||
|
typename T::key_type;
|
||||||
|
typename T::value_type;
|
||||||
|
requires std::is_same_v<typename T::key_type, typename T::value_type>; // key == value
|
||||||
|
} && requires(T t, typename T::key_type key) {
|
||||||
|
// Методы, характерные для set-like контейнеров
|
||||||
|
{ t.begin() } -> std::same_as<typename T::iterator>;
|
||||||
|
{ t.end() } -> std::same_as<typename T::iterator>;
|
||||||
|
{ t.find(key) } -> std::same_as<typename T::iterator>;
|
||||||
|
{ t.size() } -> std::convertible_to<std::size_t>;
|
||||||
|
{ t.empty() } -> std::same_as<bool>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Базовый концепт для stack-like типов
|
||||||
|
template<typename T>
|
||||||
|
concept is_stack = requires(T s) {
|
||||||
|
typename T::value_type;
|
||||||
|
typename T::container_type;
|
||||||
|
{ s.top() } -> std::same_as<typename T::value_type&>;
|
||||||
|
{ s.pop() } -> std::same_as<void>;
|
||||||
|
{ s.push(std::declval<typename T::value_type>()) } -> std::same_as<void>;
|
||||||
|
{ s.empty() } -> std::same_as<bool>;
|
||||||
|
{ s.size() } -> std::convertible_to<std::size_t>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// namespace hack::concepts
|
||||||
|
// {
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_map = std::same_as<T, std::map<typename T::key_type, typename T::mapped_type, typename T::key_compare, typename T::allocator_type>> ||
|
||||||
|
// std::same_as<T, std::unordered_map<typename T::key_type, typename T::mapped_type, typename T::hasher, typename T::key_equal, typename T::allocator_type>>;
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_tuple = requires (T t) { std::tuple_cat(t, std::make_tuple(1, "tuple")); };
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_set = std::same_as<T, std::set<typename T::key_type, typename T::key_compare, typename T::allocator_type>>;
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_unordered_set = std::same_as<T, std::unordered_set<typename T::key_type>>;
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_forward_list = std::same_as<T, std::forward_list<typename T::value_type>>;
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_string = std::is_convertible_v<T, std::string_view>;
|
||||||
|
//
|
||||||
|
// template<typename T, std::size_t N = 0>
|
||||||
|
// concept is_sequence_container = std::same_as<T, std::vector<typename T::value_type>> || std::same_as<T, std::list<typename T::value_type>> || (std::is_array_v<T> && N > 0);
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept is_associative_container = is_map<T> || is_tuple<T> || is_set<T> || is_unordered_set<T>;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// concept not_defined = !std::enable_if_t<!(std::integral<T> ||
|
||||||
|
// is_sequence_container<T> ||
|
||||||
|
// is_map<T> ||
|
||||||
|
// is_tuple<T> ||
|
||||||
|
// is_set<T> ||
|
||||||
|
// is_unordered_set<T> ||
|
||||||
|
// is_forward_list<T> ||
|
||||||
|
// std::is_array<T>() ||
|
||||||
|
// is_string<T>), bool>() == true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
src/hack/logger/logger.OLD.hpp
Executable file → Normal file
21
src/hack/logger/logger.OLD.hpp
Executable file → Normal file
@@ -10,10 +10,6 @@
|
|||||||
|
|
||||||
#include "hack/patterns/ring_buffer.hpp"
|
#include "hack/patterns/ring_buffer.hpp"
|
||||||
|
|
||||||
// HERE
|
|
||||||
// и нужно сделать реализацию где выводлится все в одной линии но при помощи цикла
|
|
||||||
// типа такого:
|
|
||||||
// for (auto i : range) hack::log(hack::log::line)(i);
|
|
||||||
namespace hack
|
namespace hack
|
||||||
{
|
{
|
||||||
class log
|
class log
|
||||||
@@ -87,8 +83,6 @@ namespace hack
|
|||||||
std::cout << " }" << (count != 0 ? devider : "");
|
std::cout << " }" << (count != 0 ? devider : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// HERE
|
|
||||||
// реализовать это с учетом новых концептов
|
|
||||||
template<concepts::is_set T>
|
template<concepts::is_set T>
|
||||||
static void print_t(const T& data)
|
static void print_t(const T& data)
|
||||||
{
|
{
|
||||||
@@ -112,7 +106,7 @@ namespace hack
|
|||||||
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(std::distance(data.cbegin(), data.cend()), std::cout));
|
std::copy(data.cbegin(), data.cend(), iterators::sequence_ostream_iterator<typename T::value_type>(std::distance(data.cbegin(), data.cend()), std::cout));
|
||||||
std::cout << " }" << (count != 0 ? devider : "");
|
std::cout << " }" << (count != 0 ? devider : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<concepts::is_map T>
|
template<concepts::is_map T>
|
||||||
static void print_t(const T& data)
|
static void print_t(const T& data)
|
||||||
{
|
{
|
||||||
@@ -127,12 +121,6 @@ namespace hack
|
|||||||
print_t(data, std::make_index_sequence<std::tuple_size<T>::value>{});
|
print_t(data, std::make_index_sequence<std::tuple_size<T>::value>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<concepts::not_defined T>
|
|
||||||
static void print_t(const T& data)
|
|
||||||
{
|
|
||||||
std::cout << data << (count != 0 ? devider : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename std::size_t... idx>
|
template<typename T, typename std::size_t... idx>
|
||||||
static void print_t(const T& data, std::index_sequence<idx...>)
|
static void print_t(const T& data, std::index_sequence<idx...>)
|
||||||
{
|
{
|
||||||
@@ -141,6 +129,12 @@ namespace hack
|
|||||||
std::cout << " }" << (count != 0 ? devider : "");
|
std::cout << " }" << (count != 0 ? devider : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<concepts::not_defined T>
|
||||||
|
static void print_t(const T& data)
|
||||||
|
{
|
||||||
|
std::cout << data << (count != 0 ? devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static void print_t(const hack::patterns::ring_buffer<T>& rb)
|
static void print_t(const hack::patterns::ring_buffer<T>& rb)
|
||||||
{
|
{
|
||||||
@@ -212,3 +206,4 @@ namespace hack
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#include "hack/utils/color.hpp"
|
#include "hack/utils/color.hpp"
|
||||||
#include "hack/patterns/singleton.hpp"
|
#include "hack/patterns/singleton.hpp"
|
||||||
#include "hack/concepts/concepts.hpp"
|
#include "hack/concepts/concepts.hpp"
|
||||||
|
#include "hack/iterators/sequence_ostream_iterator.hpp"
|
||||||
|
#include "hack/iterators/associative_ostream_iterator.hpp"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -23,12 +26,19 @@ namespace hack
|
|||||||
void set_location(std::source_location location) { m_location = location; }
|
void set_location(std::source_location location) { m_location = location; }
|
||||||
void set_devider(std::string devider) { m_devider = devider; }
|
void set_devider(std::string devider) { m_devider = devider; }
|
||||||
void no_func() { m_no_func = true; };
|
void no_func() { m_no_func = true; };
|
||||||
|
void no_file() { m_no_file = true; }
|
||||||
|
void no_row() { m_no_row = true; }
|
||||||
|
void bool_as_number() { m_bool_as_number = true; }
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
m_no_func = m_base_config.m_no_func;
|
m_no_func = m_base_config.m_no_func;
|
||||||
m_devider = m_base_config.m_devider;
|
m_devider = m_base_config.m_devider;
|
||||||
|
m_no_file = m_base_config.m_no_file;
|
||||||
|
m_no_row = m_base_config.m_no_row;
|
||||||
|
m_bool_as_number = m_base_config.m_bool_as_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void operator() (const Args&... args)
|
void operator() (const Args&... args)
|
||||||
{
|
{
|
||||||
@@ -38,23 +48,31 @@ namespace hack
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// настройки по умолчанию
|
||||||
struct config
|
struct config
|
||||||
{
|
{
|
||||||
bool m_no_func = false;
|
bool m_no_func = false; // показывать/не показывать название функции в выоде логов
|
||||||
std::string m_devider = " ";
|
bool m_no_file = false; // показывать/не показывать название файла/пути в выоде логов
|
||||||
|
bool m_no_row = false; // показывать/не показывать номер строки в выоде логов
|
||||||
|
bool m_bool_as_number = false; // показывет bool как число или как текст (0, false);
|
||||||
|
std::string m_devider = " "; // разделитель по умолчанию
|
||||||
} m_base_config;
|
} m_base_config;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << utils::color::bold << utils::color::green << "[ok]" << utils::color::reset << utils::color::green
|
ss << utils::color::bold << utils::color::green << "[ok] " << utils::color::reset;
|
||||||
<< m_location.file_name() << ":" << utils::color::reset;
|
|
||||||
|
if (!m_no_file)
|
||||||
|
ss << utils::color::green << m_location.file_name() << ":" << utils::color::reset;
|
||||||
|
|
||||||
if (!m_no_func)
|
if (!m_no_func)
|
||||||
ss << utils::color::italic << utils::color::yellow << m_location.function_name() << utils::color::reset;
|
ss << utils::color::italic << utils::color::yellow << m_location.function_name() << utils::color::reset;
|
||||||
|
|
||||||
ss << utils::color::bold << utils::color::blue << "[" << m_location.line() << "]" << utils::color::reset << ": ";
|
if (!m_no_row)
|
||||||
|
ss << utils::color::bold << utils::color::blue << "[" << m_location.line() << "] " << utils::color::reset;
|
||||||
|
|
||||||
std::cout << ss.str();
|
std::cout << ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,33 +80,128 @@ namespace hack
|
|||||||
void print_impl(const T& data, const Args&... args)
|
void print_impl(const T& data, const Args&... args)
|
||||||
{
|
{
|
||||||
--m_count;
|
--m_count;
|
||||||
pring_first(data);
|
print_t(data);
|
||||||
print_impl(args...);
|
print_impl(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_impl() { std::cout << std::endl; }
|
void print_impl() { std::cout << std::endl; }
|
||||||
|
|
||||||
template<typename T>
|
// для строк
|
||||||
requires concepts::is_string<T>
|
template<concepts::is_string T>
|
||||||
void pring_first(const T& data)
|
void print_t(const T& data)
|
||||||
{
|
{
|
||||||
std::cout << data << (m_count != 0 ? m_devider : "");
|
std::cout << data << (m_count != 0 ? m_devider : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
// для всех чисел
|
||||||
requires concepts::is_number<T>
|
template<concepts::is_number T>
|
||||||
void pring_first(const T& data)
|
void print_t(const T& data)
|
||||||
{
|
{
|
||||||
std::cout << data << (m_count != 0 ? m_devider : "");
|
std::cout << data << (m_count != 0 ? m_devider : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// для bool
|
||||||
|
template<concepts::is_bool T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
if (!m_bool_as_number)
|
||||||
|
std::cout << (data ? "true" : "false") << (m_count != 0 ? m_devider : "");
|
||||||
|
else
|
||||||
|
std::cout << data << (m_count != 0 ? m_devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// для std::vector, std::list, std::forward_list, std::deque
|
||||||
|
template<concepts::is_sequence_container T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
print_t<T, iterators::sequence_ostream_iterator>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// для std::set и подобные
|
||||||
|
template<concepts::is_set_like T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
print_t<T, iterators::sequence_ostream_iterator>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// для std::map, std::multimap
|
||||||
|
template<concepts::is_associative_container T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
print_t<T, iterators::associative_ostream_iterator>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// для std::unordered_map
|
||||||
|
template<concepts::is_unordered_associative_container T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
print_t<T, iterators::associative_ostream_iterator>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Вспомогательнгая функция для контейнеров выше
|
||||||
|
template<typename T, template<typename> class Iterator>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
std::cout << "{ ";
|
||||||
|
|
||||||
|
// Вычисляем размер для контейнеров, которые не имеют метода size()
|
||||||
|
std::size_t size = 0;
|
||||||
|
if constexpr (requires { data.size(); })
|
||||||
|
size = data.size();
|
||||||
|
else
|
||||||
|
size = std::distance(data.cbegin(), data.cend());
|
||||||
|
|
||||||
|
std::copy(data.cbegin(), data.cend(), Iterator<typename T::value_type>(size, std::cout));
|
||||||
|
std::cout << " }" << (m_count != 0 ? m_devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Основная функция для tuple
|
||||||
|
template<concepts::is_tuple_like T>
|
||||||
|
void print_t(const T& data)
|
||||||
|
{
|
||||||
|
std::cout << "{ ";
|
||||||
|
print_t(data, std::make_index_sequence<std::tuple_size_v<T>>{});
|
||||||
|
std::cout << " }" << (m_count != 0 ? m_devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t... idx>
|
||||||
|
void print_t(const T& data, std::index_sequence<idx...>)
|
||||||
|
{
|
||||||
|
((std::cout << std::get<idx>(data) << (idx != std::tuple_size<T>::value - 1 ? m_devider : "")), ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Для stack - выводим содержимое (но stack нельзя итерировать!)
|
||||||
|
template<concepts::is_stack T>
|
||||||
|
void print_t(const T& stack)
|
||||||
|
{
|
||||||
|
T temp = stack;
|
||||||
|
|
||||||
|
std::cout << "{ ";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
while (!temp.empty())
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
std::cout << m_devider;
|
||||||
|
first = false;
|
||||||
|
std::cout << temp.top();
|
||||||
|
temp.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << " }" << (m_count != 0 ? m_devider : "");
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::source_location m_location;
|
std::source_location m_location;
|
||||||
std::size_t m_count = 0;
|
std::size_t m_count = 0;
|
||||||
std::string m_devider = m_base_config.m_devider;
|
std::string m_devider = m_base_config.m_devider;
|
||||||
bool m_no_func = m_base_config.m_no_func;
|
bool m_no_func = m_base_config.m_no_func;
|
||||||
|
bool m_no_file = m_base_config.m_no_file;
|
||||||
|
bool m_no_row = m_base_config.m_no_row;
|
||||||
|
bool m_bool_as_number = m_base_config.m_bool_as_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// основная функция вызова логера
|
||||||
inline logger& log(std::source_location location = std::source_location::current())
|
inline logger& log(std::source_location location = std::source_location::current())
|
||||||
{
|
{
|
||||||
logger::instance().set_location(location);
|
logger::instance().set_location(location);
|
||||||
|
|||||||
Reference in New Issue
Block a user