From d2a87d5803c7aaa9a47791a5a0f1494c19671ebc Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 26 Apr 2022 20:16:22 +0200 Subject: add project & make some tweaks Added from https://git.hampusmat.com/game-of-life --- .clang-format | 19 ++ .clang-tidy | 44 +++++ .gitignore | 2 + CMakeLists.txt | 15 ++ README.md | 1 + include/yacppdic/auto_wirable.hpp | 20 +++ include/yacppdic/concepts.hpp | 16 ++ include/yacppdic/container.hpp | 65 +++++++ include/yacppdic/detail/auto_wirable-impl.hpp | 16 ++ include/yacppdic/detail/container-impl.hpp | 94 ++++++++++ include/yacppdic/detail/factory-impl.hpp | 70 ++++++++ .../detail/internal/alloc_destructor-impl.hpp | 23 +++ .../yacppdic/detail/internal/alloc_destructor.hpp | 37 ++++ .../detail/internal/compressed_pair-impl.hpp | 46 +++++ .../yacppdic/detail/internal/compressed_pair.hpp | 199 +++++++++++++++++++++ .../detail/internal/functor/alloc_functor-impl.hpp | 186 +++++++++++++++++++ .../detail/internal/functor/alloc_functor.hpp | 89 +++++++++ .../internal/functor/copyable_functor-impl.hpp | 112 ++++++++++++ .../detail/internal/functor/copyable_functor.hpp | 52 ++++++ .../detail/internal/functor/value_functor-impl.hpp | 196 ++++++++++++++++++++ .../detail/internal/functor/value_functor.hpp | 70 ++++++++ .../internal/interfaces/copyable_functor.hpp | 46 +++++ include/yacppdic/detail/internal/misc_concepts.hpp | 11 ++ .../yacppdic/detail/internal/strip_signature.hpp | 108 +++++++++++ include/yacppdic/detail/internal/type_utils.hpp | 35 ++++ .../internal/wrapper/function_wrapper-impl.hpp | 22 +++ .../detail/internal/wrapper/function_wrapper.hpp | 26 +++ .../internal/wrapper/object_wrapper-impl.hpp | 15 ++ .../detail/internal/wrapper/object_wrapper.hpp | 26 +++ include/yacppdic/detail/object_type-impl.hpp | 29 +++ include/yacppdic/factory.hpp | 171 ++++++++++++++++++ include/yacppdic/interfaces/wrapper.hpp | 17 ++ include/yacppdic/object_type.hpp | 34 ++++ include/yacppdic/type_traits.hpp | 23 +++ test/CMakeLists.txt | 47 +++++ test/container.test.cpp | 41 +++++ test/lib/CMakeLists.txt | 3 + test/lib/gtest/CMakeLists.txt | 9 + 38 files changed, 2035 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 include/yacppdic/auto_wirable.hpp create mode 100644 include/yacppdic/concepts.hpp create mode 100644 include/yacppdic/container.hpp create mode 100644 include/yacppdic/detail/auto_wirable-impl.hpp create mode 100644 include/yacppdic/detail/container-impl.hpp create mode 100644 include/yacppdic/detail/factory-impl.hpp create mode 100644 include/yacppdic/detail/internal/alloc_destructor-impl.hpp create mode 100644 include/yacppdic/detail/internal/alloc_destructor.hpp create mode 100644 include/yacppdic/detail/internal/compressed_pair-impl.hpp create mode 100644 include/yacppdic/detail/internal/compressed_pair.hpp create mode 100644 include/yacppdic/detail/internal/functor/alloc_functor-impl.hpp create mode 100644 include/yacppdic/detail/internal/functor/alloc_functor.hpp create mode 100644 include/yacppdic/detail/internal/functor/copyable_functor-impl.hpp create mode 100644 include/yacppdic/detail/internal/functor/copyable_functor.hpp create mode 100644 include/yacppdic/detail/internal/functor/value_functor-impl.hpp create mode 100644 include/yacppdic/detail/internal/functor/value_functor.hpp create mode 100644 include/yacppdic/detail/internal/interfaces/copyable_functor.hpp create mode 100644 include/yacppdic/detail/internal/misc_concepts.hpp create mode 100644 include/yacppdic/detail/internal/strip_signature.hpp create mode 100644 include/yacppdic/detail/internal/type_utils.hpp create mode 100644 include/yacppdic/detail/internal/wrapper/function_wrapper-impl.hpp create mode 100644 include/yacppdic/detail/internal/wrapper/function_wrapper.hpp create mode 100644 include/yacppdic/detail/internal/wrapper/object_wrapper-impl.hpp create mode 100644 include/yacppdic/detail/internal/wrapper/object_wrapper.hpp create mode 100644 include/yacppdic/detail/object_type-impl.hpp create mode 100644 include/yacppdic/factory.hpp create mode 100644 include/yacppdic/interfaces/wrapper.hpp create mode 100644 include/yacppdic/object_type.hpp create mode 100644 include/yacppdic/type_traits.hpp create mode 100644 test/CMakeLists.txt create mode 100644 test/container.test.cpp create mode 100644 test/lib/CMakeLists.txt create mode 100644 test/lib/gtest/CMakeLists.txt diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..782b0a9 --- /dev/null +++ b/.clang-format @@ -0,0 +1,19 @@ +BasedOnStyle: LLVM +UseTab: Always +IndentWidth: 4 +TabWidth: 4 +BreakBeforeBraces: Allman +AllowShortIfStatementsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: None +IndentCaseLabels: false +ColumnLimit: 90 +AccessModifierOffset: -4 +AlwaysBreakTemplateDeclarations: Yes +ConstructorInitializerAllOnOneLineOrOnePerLine: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +BinPackArguments: false +BinPackParameters: false +AlignAfterOpenBracket: BlockIndent +Cpp11BracedListStyle: false diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..9c19cf2 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,44 @@ +--- +Checks: ' + clang-analyzer-*, + cppcoreguidelines-*, + google-*, + misc-*, + modernize-*, + bugprone-*, + performance-*, + readability-*, + -cppcoreguidelines-pro-type-union-access' +WarningsAsErrors: '*' +HeaderFilterRegex: '\/src\/' +AnalyzeTemporaryDtors: false +CheckOptions: + - key: readability-function-cognitive-complexity.Threshold + value: 100 + - key: readability-identifier-naming.ClassCase + value: CamelCase + - key: readability-identifier-naming.PrivateMemberPrefix + value: _ + - key: readability-identifier-naming.StructCase + value: CamelCase + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' +... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af96791 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9810762 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.2.0) + +project(yacppdic CXX) + +add_library(${PROJECT_NAME} INTERFACE) + +target_include_directories( + ${PROJECT_NAME} + INTERFACE + $ +) + +add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) + +add_subdirectory(test) diff --git a/README.md b/README.md new file mode 100644 index 0000000..f996018 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Yet another C++ Dependency Injection Container diff --git a/include/yacppdic/auto_wirable.hpp b/include/yacppdic/auto_wirable.hpp new file mode 100644 index 0000000..09cef65 --- /dev/null +++ b/include/yacppdic/auto_wirable.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "yacppdic/container.hpp" + +#include + +namespace yacppdic +{ + +template +class AutoWirable +{ +public: + static auto resolve(const Container &container) noexcept + -> std::unique_ptr; +}; + +} // namespace yacppdic + +#include "yacppdic/detail/auto_wirable-impl.hpp" diff --git a/include/yacppdic/concepts.hpp b/include/yacppdic/concepts.hpp new file mode 100644 index 0000000..d8097df --- /dev/null +++ b/include/yacppdic/concepts.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "yacppdic/type_traits.hpp" + +#include + +namespace yacppdic +{ + +template +concept Abstract = std::is_abstract_v; + +template +concept IsFactory = is_factory_v; + +} diff --git a/include/yacppdic/container.hpp b/include/yacppdic/container.hpp new file mode 100644 index 0000000..f8ffb90 --- /dev/null +++ b/include/yacppdic/container.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "yacppdic/interfaces/wrapper.hpp" + +#include "yacppdic/concepts.hpp" +#include "yacppdic/factory.hpp" +#include "yacppdic/object_type.hpp" + +#include +#include +#include +#include + +namespace yacppdic +{ + +class Container; + +template +class BindingBuilder +{ +public: + explicit BindingBuilder(Container *container) noexcept; + + template + requires Abstract && std::derived_from + void to() noexcept; + + template + requires IsFactory && std::constructible_from + void to_factory(FactoryFunc factory) noexcept; + +private: + Container *_container; +}; + +class Container +{ +public: + Container() noexcept = default; + + template + using WrapperPtr = std::shared_ptr; + + template + auto bind() noexcept -> BindingBuilder; + + template + requires Abstract + auto get() const noexcept -> std::unique_ptr; + + template + requires IsFactory + auto get() const noexcept -> AFactory; + + void add(BaseObjectType type, const WrapperPtr &wrapper) noexcept; + +private: + std::unordered_map, ObjectTypeHasher> + _bindings; +}; + +} // namespace yacppdic + +#include "yacppdic/detail/container-impl.hpp" diff --git a/include/yacppdic/detail/auto_wirable-impl.hpp b/include/yacppdic/detail/auto_wirable-impl.hpp new file mode 100644 index 0000000..e2dafa9 --- /dev/null +++ b/include/yacppdic/detail/auto_wirable-impl.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "yacppdic/auto_wirable.hpp" + +namespace yacppdic +{ + +template +auto AutoWirable::resolve( + const Container &container +) noexcept -> std::unique_ptr +{ + return std::make_unique(container.get()...); +} + +} // namespace yacppdic diff --git a/include/yacppdic/detail/container-impl.hpp b/include/yacppdic/detail/container-impl.hpp new file mode 100644 index 0000000..897b8c3 --- /dev/null +++ b/include/yacppdic/detail/container-impl.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include "yacppdic/container.hpp" +#include "yacppdic/detail/internal/wrapper/function_wrapper.hpp" +#include "yacppdic/detail/internal/wrapper/object_wrapper.hpp" + +#include + +namespace yacppdic +{ + +template +BindingBuilder::BindingBuilder(Container *container) noexcept + : _container(container) +{ +} + +template +template +requires Abstract && std::derived_from +void BindingBuilder::to() noexcept +{ + using Wrapper = internal::ObjectWrapper; + + auto wrapper = Container::WrapperPtr(new Wrapper(*_container)); + + _container->add( + ObjectType(), + std::dynamic_pointer_cast(wrapper) + ); +} + +template +template +requires IsFactory && std::constructible_from +void BindingBuilder::to_factory(FactoryFunc factory) noexcept +{ + using Wrapper = internal::FunctionWrapper; + + auto wrapper = Container::WrapperPtr(new Wrapper(factory)); + + _container->add( + ObjectType(), + std::dynamic_pointer_cast(wrapper) + ); +} + +template +auto Container::bind() noexcept -> BindingBuilder +{ + return BindingBuilder(this); +} + +template +requires Abstract +auto Container::get() const noexcept -> std::unique_ptr +{ + ObjectType interface_type; + + if (_bindings.count(interface_type) == 0) + { + std::cerr + << "Error: Tried to get a item from the container using unbound interface '" + << interface_type.name() << "'" << std::endl; + exit(EXIT_FAILURE); + } + + auto wrapper = std::dynamic_pointer_cast>>( + _bindings.at(interface_type) + ); + + return wrapper->get(); +} + +template +requires IsFactory +auto Container::get() const noexcept -> AFactory +{ + auto wrapper = + std::dynamic_pointer_cast>(_bindings.at(ObjectType()) + ); + + return wrapper->get(); +} + +void Container::add( + BaseObjectType type, + const WrapperPtr &wrapper +) noexcept +{ + _bindings.insert({ type, wrapper }); +} + +} // namespace yacppdic diff --git a/include/yacppdic/detail/factory-impl.hpp b/include/yacppdic/detail/factory-impl.hpp new file mode 100644 index 0000000..3deede2 --- /dev/null +++ b/include/yacppdic/detail/factory-impl.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "yacppdic/factory.hpp" + +namespace yacppdic +{ + +template +Factory::Factory(const Factory &factory) : _functor(factory._functor) +{ +} + +template +Factory::Factory(Factory &&factory) noexcept + : _functor(std::move(factory._functor)) +{ +} + +template +auto Factory::operator=(Factory &&factory) noexcept + -> Factory & +{ + _functor = std::move(factory._functor); + return *this; +} + +template +auto Factory::operator=(std::nullptr_t) noexcept + -> Factory & +{ + _functor = nullptr; + return *this; +} + +template +Factory::~Factory() = default; + +template +Factory::operator bool() const noexcept +{ + return static_cast(_functor); +} + +template +auto Factory::operator()(Args... args) const -> Return +{ + return _functor(std::forward(args)...); +} + +template +auto Factory::target_type() const noexcept -> const std::type_info & +{ + return _functor.target_type(); +} + +template +template +auto Factory::target() noexcept -> Tp * +{ + return static_cast(_functor.template target()); +} + +template +template +auto Factory::target() const noexcept -> const Tp * +{ + return _functor.template target(); +} + +} diff --git a/include/yacppdic/detail/internal/alloc_destructor-impl.hpp b/include/yacppdic/detail/internal/alloc_destructor-impl.hpp new file mode 100644 index 0000000..abcabba --- /dev/null +++ b/include/yacppdic/detail/internal/alloc_destructor-impl.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "alloc_destructor.hpp" + +namespace yacppdic::internal +{ + +template +AllocDestructor::AllocDestructor( + Allocator &allocator, + Size alloc_size +) noexcept + : _allocator(allocator), _size(alloc_size) +{ +} + +template +void AllocDestructor::operator()(Pointer ptr) noexcept +{ + _alloc_traits::deallocate(_allocator, ptr, _size); +} + +} diff --git a/include/yacppdic/detail/internal/alloc_destructor.hpp b/include/yacppdic/detail/internal/alloc_destructor.hpp new file mode 100644 index 0000000..9160b8b --- /dev/null +++ b/include/yacppdic/detail/internal/alloc_destructor.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace yacppdic::internal +{ + +template +struct RebindAllocHelper +{ + using type = typename Traits::template rebind_alloc; +}; + +template +class AllocDestructor +{ + using _alloc_traits = std::allocator_traits; + +public: + using Pointer = typename _alloc_traits::pointer; + using Size = typename _alloc_traits::size_type; + + using pointer = Pointer; + using size = Size; + + AllocDestructor(Allocator &allocator, Size alloc_size) noexcept; + + void operator()(Pointer ptr) noexcept; + +private: + Allocator &_allocator; + Size _size; +}; + +} // namespace yacppdic::internal + +#include "alloc_destructor-impl.hpp" diff --git a/include/yacppdic/detail/internal/compressed_pair-impl.hpp b/include/yacppdic/detail/internal/compressed_pair-impl.hpp new file mode 100644 index 0000000..0e2a322 --- /dev/null +++ b/include/yacppdic/detail/internal/compressed_pair-impl.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include "compressed_pair.hpp" + +namespace yacppdic::internal +{ + +template +constexpr CompressedPairElement::CompressedPairElement( + DefaultInitTag /*default_init_tag*/ +) +{ +} + +template +constexpr CompressedPairElement::CompressedPairElement( + ValueInitTag /*value_init_tag*/ +) + : _value() +{ +} + +template +template +constexpr CompressedPairElement::CompressedPairElement( + std::piecewise_construct_t /*tag_types*/, + std::tuple args, + TupleIndices /*indices*/ +) + : _value(std::forward(std::get(args))...) +{ +} + +template +auto CompressedPairElement::get() noexcept -> ValueReference +{ + return _value; +} + +template +auto CompressedPairElement::get() const noexcept -> ConstValueReference +{ + return _value; +} + +} // namespace yacppdic::internal diff --git a/include/yacppdic/detail/internal/compressed_pair.hpp b/include/yacppdic/detail/internal/compressed_pair.hpp new file mode 100644 index 0000000..3c832c5 --- /dev/null +++ b/include/yacppdic/detail/internal/compressed_pair.hpp @@ -0,0 +1,199 @@ +#pragma once + +#include "yacppdic/detail/internal/misc_concepts.hpp" + +#include +#include +#include +#include + +namespace yacppdic::internal +{ + +// Tag used to default initialize one or both of the pair's elements. +struct DefaultInitTag +{ +}; + +struct ValueInitTag +{ +}; + +template +struct TupleIndices +{ +}; + +template +struct IntegerSequence +{ + template