Header only C++17 extensions library
Usage simple with .Net Microsoft.Extensions.DependencyInjection
Example
#include <ext/core/dependency_injection.h>
struct InterfaceExample
{
virtual ~InterfaceExample() = default;
};
struct InterfaceImplementationExample : InterfaceExample
{};
struct CreatedObjectExample : ext::ServiceProviderHolder
{
explicit CreatedObjectExample(std::shared_ptr<InterfaceExample> interfaceShared, std::lazy_interface<InterfaceExample> interfaceLazy, ext::ServiceProvider::Ptr&& serviceProvider)
: ServiceProviderHolder(std::move(serviceProvider))
, m_interfaceShared(std::move(interfaceShared))
, m_interfaceLazyOne(std::move(interfaceLazy))
, m_interfaceLazyTwo(ServiceProviderHolder::m_serviceProvider)
{}
std::shared_ptr<IRandomInterface> GetRandomInterface() const
{
return ServiceProviderHolder::GetInterface<IRandomInterface>();
}
std::shared_ptr<IRandomInterface> GetRandomInterfaceOption2() const
{
return ext::GetInterface<IRandomInterface>(ServiceProviderHolder::m_serviceProvider);
}
std::shared_ptr<InterfaceExample> m_interfaceShared;
ext::lazy_interface<InterfaceExample> m_interfaceLazyOne;
ext::lazy_interface<InterfaceExample> m_interfaceLazyTwo;
};
ext::ServiceCollection& serviceCollection = ext::get_singleton<ext::ServiceCollection>();
serviceCollection.RegisterScoped<InterfaceImplementationExample, InterfaceExample>();
const std::shared_ptr<CreatedObjectExample> object = ext::CreateObject<CreatedObjectExample>(serviceCollection.BuildServiceProvider());
Serialization objects to/from text, xml
Example
#include <ext/serialization/iserializable.h>
using namespace ext::serializable;
using namespace ext::serializer;
struct Settings
{
struct User
{
REGISTER_SERIALIZABLE_OBJECT();
DECLARE_SERIALIZABLE_FIELD(std::int64_t, id);
DECLARE_SERIALIZABLE_FIELD(std::string, firstName);
DECLARE_SERIALIZABLE_FIELD(std::string, userName);
};
REGISTER_SERIALIZABLE_OBJECT_N("My settings");
DECLARE_SERIALIZABLE_FIELD(std::wstring, token);
DECLARE_SERIALIZABLE_FIELD(std::wstring, password);
DECLARE_SERIALIZABLE_FIELD(std::list<User>, registeredUsers);
Settings(){
std::wstring text;
if (!DeserializeObject(Factory::TextDeserializer(text), *this))
...
}
~Settings() {
std::wstring text;
if (!SerializeObject(Factory::TextSerializer(text), *this))
...
}
};
Allow to register events and notify subscribers
Example
#include <ext/core/dispatcher.h>
// Example of event interface
struct IEvent : ext::events::IBaseEvent
{
virtual void Event(int val) = 0;
};
// Example of sending an event:
ext::send_event(&IEvent::Event, 10);
// Example of recipient:
struct Recipient : ext::events::ScopeSubscription<IEvent>
{
void Event(int val) override { std::cout << "Event"; }
}
Interruptible thread(boost/thread analog)
#include <ext/thread/thread.h>
ext::thread myThread(thread_function, []()
{
while (!ext::this_thread::interruption_requested())
{
try
{
...
}
catch (const ext::thread::thread_interrupted&)
{
break;
}
}
});
myThread.interrupt();
EXPECT_TRUE(myThread.interrupted());
Thread pool
#include <ext/thread/thread_pool.h>
std::set<ext::task::TaskId, ext::task::TaskIdComparer> taskList;
ext::thread_pool threadPool([&taskList, &listMutex](const ext::task::TaskId& taskId)
{
taskList.erase(taskId);
});
const auto maxThreads = std::thread::hardware_concurrency();
for (auto i = maxThreads; i != 0; --i)
{
taskList.emplace(threadPool.add_task([]()
{
...
}));
}
threadPool.wait_for_tasks();
- Task scheduler
- Main thread methods invoker(for GUI and other synchronized actions)
- Event
- Tick timer, allow to synchronize sth(for example animations)
- Wait group(GO analog)
- Channel(GO analog)
ext::Channel<int> channel;
std::thread([&]()
{
for (auto val : channel) {
...
}
});
channel.add(1);
channel.add(10);
channel.close();
ext::stop_source source;
ext::thread myThread([stop_token = source.get_token()]()
{
while (!stop_token.stop_requested())
{
...
}
});
source.request_stop();
myThread.join();
Show traces with defferent levels and time stamps in cout/cerr/output/trace file
#include <ext/core/tracer.h>
ext::get_tracer().Enable();
Simple macroses:
Default information trace
EXT_TRACE() << "My trace";
Debug information only for Debug build
EXT_TRACE_DBG() << EXT_TRACE_FUNCTION "called";
Error trace to cerr, mostly used in EXT_CHECK/EXT_EXPECT
EXT_TRACE_ERR() << EXT_TRACE_FUNCTION "called";
Can be called for scope call function check. Trace start and end scope with the given text
EXT_TRACE_SCOPE() << EXT_TRACE_FUNCTION << "Main function called with " << args;
Allows to add simple checks inside executing code and manage ezxceptions
#include <ext/core/check.h>
EXT_CHECK - throws exception if expression is false
EXT_CHECK(bool_expression) << "Text";
if (!bool_expression)
throw ::ext::check::CheckFailedException(EXT_SRC_LOCATION, #bool_expression "Text");
EXT_EXPECT - if expression is false:
- Only on first failure: debug break if debugger presents, create dump otherwise
- throws exception
EXT_EXPECT(bool_expression) << "Text";
if (!bool_expression)
{
if (IsDebuggerPresent())
DebugBreak();
else
EXT_DUMP_CREATE();
throw ::ext::check::CheckFailedException(EXT_SRC_LOCATION, #bool_expression "Text"));
}
EXT_ASSERT / EXT_REQUIRE - if expression is false in debug mode. Only on first failure: debug break if debugger presents, create dump otherwise
EXT_ASSERT(bool_expression) << "Text";
#ifdef _DEBUG
if (!bool_expression)
{
if (IsDebuggerPresent())
DebugBreak();
else
EXT_DUMP_CREATE();
}
#endif
Allow to simplify managing exceptions and output error text
#include <ext/error/exception.h>
try
{
EXT_EXPECT(is_ok()) << "Something wrong!";
}
catch (...)
{
try
{
std::throw_with_nested(ext::exception(EXT_SRC_LOCATION, "Job failed"));
}
catch (...)
{
::MessageBox(NULL, ext::ManageExceptionText("Big bang"));
}
}
Allow to catch unhandled exceptions and generate dump file
Declare unhandled exceptions handler(called automatic on calling ext::dump::create_dump())
#include <ext/error/dump_writer.h>
void main()
{
EXT_DUMP_DECLARE_HANDLER();
...
}
If you need to catch error inside you code you add check:
EXT_DUMP_IF(is_something_wrong());
In this case if debugger presents - it will be stopped here, otherwise generate dump file and continue execution, @see DEBUG_BREAK_OR_CREATE_DUMP. Dump generation and debug break in case with EXT_DUMP_IF generates only once to avoid spam.
Constexpr string
Allows to combine and check text in compile time.
#include <ext/constexpr/string.h>
constexpr ext::constexpr_string textFirst = "test";
constexpr ext::constexpr_string textSecond = "second";
constexpr auto TextCombination = textFirst + "_" + textSecond;
static_assert(TextCombination == "test_second");
In C++20 can be used to store text as a template argument:
template <ext::constexpr_string name__>
struct Object {
constexpr std::string_view Name() const {
return name__.str();
}
...
};
Object<"object_name"> object;
static_assert(object.Name() == std::string_view("object_name"));
Constexpr map
Compile time extension for strings, allow to combine and check text in compile time.
#include <ext/constexpr/map.h>
constexpr ext::constexpr_map my_map = {{std::pair{11, 10}, {std::pair{22, 33}}}};
static_assert(my_map.size() == 2);
static_assert(10 == my_map.get_value(11));
static_assert(33 == my_map.get_value(22));
- lazy_shared_ptr - allow to create a shared memory which will be created only on first call
- Call once(GO analog)
- Thread safe singleton with lifetime check
- Extension for tuples/variants and types array
- Auto setter on scope change
- Defer (GO analog)
- Object holder
CMake build and run tests
mkdir build
cd build
cmake .. -DEXT_BUILD_TESTS=ON
cmake --build . --parallel
# On windows
.\tests\Debug\ext_tests.exe
# On linux
./tests/ext_tests