diff options
author | HampusM <hampus@hampusmat.com> | 2022-02-27 12:54:10 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2022-06-13 17:56:53 +0200 |
commit | 5864e5abc43b201c3801fa39a2fcaf9e3a9e8914 (patch) | |
tree | 98e5e324066ef4d1cbd3cc4c792a258fbd86c12d | |
parent | e233dc28491c33e8a7dc0a11576d3b8ce91cce2c (diff) |
refactor: use dependency injection
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/DI/auto_wirable.hpp | 28 | ||||
-rw-r--r-- | src/DI/auto_wirable.tpp | 10 | ||||
-rw-r--r-- | src/DI/container.hpp | 65 | ||||
-rw-r--r-- | src/DI/container.tpp | 53 | ||||
-rw-r--r-- | src/DI/function_wrapper.hpp | 20 | ||||
-rw-r--r-- | src/DI/function_wrapper.tpp | 9 | ||||
-rw-r--r-- | src/DI/interfaces/wrapper.hpp | 17 | ||||
-rw-r--r-- | src/DI/object_type.cpp | 18 | ||||
-rw-r--r-- | src/DI/object_type.hpp | 35 | ||||
-rw-r--r-- | src/DI/object_wrapper.hpp | 20 | ||||
-rw-r--r-- | src/DI/object_wrapper.tpp | 9 | ||||
-rw-r--r-- | src/argument_parser.cpp | 100 | ||||
-rw-r--r-- | src/argument_parser.hpp | 27 | ||||
-rw-r--r-- | src/bootstrap.cpp | 36 | ||||
-rw-r--r-- | src/bootstrap.hpp | 5 | ||||
-rw-r--r-- | src/game_of_life.cpp | 97 | ||||
-rw-r--r-- | src/interfaces/argument_parser.hpp | 23 | ||||
-rw-r--r-- | src/interfaces/randomization.hpp | 31 | ||||
-rw-r--r-- | src/randomization.hpp | 35 | ||||
-rw-r--r-- | src/randomization/generator.cpp (renamed from src/randomization.cpp) | 9 | ||||
-rw-r--r-- | src/randomization/generator.hpp | 18 | ||||
-rw-r--r-- | src/randomization/seed_generator.cpp | 11 | ||||
-rw-r--r-- | src/randomization/seed_generator.hpp | 17 |
24 files changed, 574 insertions, 125 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e4d106..54ee94f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,8 +10,12 @@ endfunction(target_link_libraries_system) file(GLOB SOURCES game_of_life.cpp + bootstrap.cpp conversion.cpp - randomization.cpp) + argument_parser.cpp + randomization/generator.cpp + randomization/seed_generator.cpp + DI/object_type.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/DI/auto_wirable.hpp b/src/DI/auto_wirable.hpp new file mode 100644 index 0000000..13d252e --- /dev/null +++ b/src/DI/auto_wirable.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "DI/container.hpp" + +#include <memory> + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class IGenericAutoWirable +{ +public: + virtual ~IGenericAutoWirable() = default; +}; + +template <class Interface> +class IAutoWirable : public IGenericAutoWirable +{ +public: + static Interface resolve(); +}; + +template <class Interface, class ObjectImpl, class... Dependencies> +class AutoWirable : public IAutoWirable<Interface> +{ +public: + static std::shared_ptr<Interface> resolve(const Container &container); +}; + +#include "auto_wirable.tpp" diff --git a/src/DI/auto_wirable.tpp b/src/DI/auto_wirable.tpp new file mode 100644 index 0000000..6c0d111 --- /dev/null +++ b/src/DI/auto_wirable.tpp @@ -0,0 +1,10 @@ +#pragma once + +#include "auto_wirable.hpp" + +template <class Interface, class ObjectImpl, class... Dependencies> +std::shared_ptr<Interface> +AutoWirable<Interface, ObjectImpl, Dependencies...>::resolve(const Container &container) +{ + return std::make_shared<ObjectImpl>(container.get<Dependencies>()...); +} diff --git a/src/DI/container.hpp b/src/DI/container.hpp new file mode 100644 index 0000000..2402894 --- /dev/null +++ b/src/DI/container.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "DI/object_type.hpp" +#include "interfaces/wrapper.hpp" + +#include <functional> +#include <memory> +#include <type_traits> +#include <unordered_map> + +class Container; + +template <typename Interface> +class BindingBuilder +{ +public: + explicit BindingBuilder(Container *container); + + template <class ObjectImpl, + class = std::enable_if_t<std::is_base_of_v<Interface, ObjectImpl>>> + void to(); + + void to_factory(Interface func); + +private: + Container *_container; +}; + +template <typename Satan> +struct is_func : public std::false_type // NOLINT(readability-identifier-naming) +{ +}; + +template <typename Satan, typename... Args> +struct is_func<std::function<Satan(Args...)>> : public std::true_type +{ +}; + +class Container +{ +public: + Container() = default; + + template <class Interface> + BindingBuilder<Interface> bind(); + + template <class Interface, class = std::enable_if_t<std::is_abstract_v<Interface>>> + std::shared_ptr<Interface> get() const; + + /* + template <typename Interface, + typename = std::enable_if_t< + !std::is_abstract_v<Interface> && + std::is_invocable_v<Interface, typename Interface::argument_type>>> + Interface get() const; + */ + + template <typename Interface, typename = std::enable_if_t<is_func<Interface>::value>> + Interface get() const; + + std::unordered_map<BaseObjectType, std::shared_ptr<IGenericWrapper>, ObjectTypeHasher> + bindings; +}; + +#include "container.tpp" diff --git a/src/DI/container.tpp b/src/DI/container.tpp new file mode 100644 index 0000000..21bf81a --- /dev/null +++ b/src/DI/container.tpp @@ -0,0 +1,53 @@ +#pragma once + +#include "container.hpp" + +#include "function_wrapper.hpp" +#include "object_wrapper.hpp" + +template <class Interface> +BindingBuilder<Interface>::BindingBuilder(Container *container) : _container(container) +{ +} + +template <class Interface> +template <class ObjectImpl, class> +void BindingBuilder<Interface>::to() +{ + _container->bindings.emplace( + ObjectType<Interface>(), + std::dynamic_pointer_cast<IGenericWrapper>( + std::make_shared<ObjectWrapper<Interface, ObjectImpl>>(*_container))); +} + +template <class Interface> +void BindingBuilder<Interface>::to_factory(Interface func) +{ + _container->bindings.emplace(ObjectType<Interface>(), + std::dynamic_pointer_cast<IGenericWrapper>( + std::make_shared<FunctionWrapper<Interface>>(func))); +} + +template <class Interface> +BindingBuilder<Interface> Container::bind() +{ + return BindingBuilder<Interface>(this); +} + +template <class Interface, class> +std::shared_ptr<Interface> Container::get() const +{ + auto wrapper = std::dynamic_pointer_cast<IWrapper<std::shared_ptr<Interface>>>( + bindings.at(ObjectType<Interface>())); + + return wrapper->get(); +} + +template <typename Interface, typename> +Interface Container::get() const +{ + auto wrapper = std::dynamic_pointer_cast<IWrapper<Interface>>( + bindings.at(ObjectType<Interface>())); + + return wrapper->get(); +} diff --git a/src/DI/function_wrapper.hpp b/src/DI/function_wrapper.hpp new file mode 100644 index 0000000..e4b6779 --- /dev/null +++ b/src/DI/function_wrapper.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "DI/container.hpp" +#include "DI/interfaces/wrapper.hpp" + +#include <memory> + +template <class Interface> +class FunctionWrapper : public IWrapper<Interface> +{ +public: + explicit FunctionWrapper(Interface func) : _func(func) {} + + [[nodiscard]] Interface get() const; + +private: + const Interface _func; +}; + +#include "function_wrapper.tpp" diff --git a/src/DI/function_wrapper.tpp b/src/DI/function_wrapper.tpp new file mode 100644 index 0000000..4e09957 --- /dev/null +++ b/src/DI/function_wrapper.tpp @@ -0,0 +1,9 @@ +#pragma once + +#include "function_wrapper.hpp" + +template <class Interface> +Interface FunctionWrapper<Interface>::get() const +{ + return _func; +} diff --git a/src/DI/interfaces/wrapper.hpp b/src/DI/interfaces/wrapper.hpp new file mode 100644 index 0000000..3cc75a0 --- /dev/null +++ b/src/DI/interfaces/wrapper.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include <memory> + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions) +class IGenericWrapper +{ +public: + virtual ~IGenericWrapper() = default; +}; + +template <class Interface> +class IWrapper : public IGenericWrapper +{ +public: + [[nodiscard]] virtual Interface get() const = 0; +}; diff --git a/src/DI/object_type.cpp b/src/DI/object_type.cpp new file mode 100644 index 0000000..60c7c78 --- /dev/null +++ b/src/DI/object_type.cpp @@ -0,0 +1,18 @@ +#include "object_type.hpp" + +BaseObjectType::BaseObjectType(const std::type_info &type_info) : _type_info(type_info) {} + +bool BaseObjectType::operator==(const BaseObjectType &object_type) const +{ + return hash() == object_type.hash(); +} + +std::size_t BaseObjectType::hash() const +{ + return _type_info.hash_code(); +} + +std::size_t ObjectTypeHasher::operator()(const BaseObjectType &object_type) const +{ + return object_type.hash(); +} diff --git a/src/DI/object_type.hpp b/src/DI/object_type.hpp new file mode 100644 index 0000000..f690a64 --- /dev/null +++ b/src/DI/object_type.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include <typeinfo> + +class BaseObjectType +{ +public: + explicit BaseObjectType(const std::type_info &type_info); + + bool operator==(const BaseObjectType &object_type) const; + + [[nodiscard]] std::size_t hash() const; + +private: + const std::type_info &_type_info; +}; + +template <class Object> +class ObjectType : public BaseObjectType +{ +public: + ObjectType() : BaseObjectType(typeid(Object)) {} +}; + +class IObjectTypeHasher +{ +public: + virtual std::size_t operator()(const BaseObjectType &object_type) const = 0; +}; + +class ObjectTypeHasher : public IObjectTypeHasher +{ +public: + std::size_t operator()(const BaseObjectType &object_type) const override; +}; diff --git a/src/DI/object_wrapper.hpp b/src/DI/object_wrapper.hpp new file mode 100644 index 0000000..0ae66df --- /dev/null +++ b/src/DI/object_wrapper.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "DI/container.hpp" +#include "DI/interfaces/wrapper.hpp" + +#include <memory> + +template <class Interface, class ObjectImpl> +class ObjectWrapper : public IWrapper<std::shared_ptr<Interface>> +{ +public: + explicit ObjectWrapper(const Container &container) : _container(container) {} + + [[nodiscard]] std::shared_ptr<Interface> get() const; + +private: + const Container &_container; +}; + +#include "object_wrapper.tpp" diff --git a/src/DI/object_wrapper.tpp b/src/DI/object_wrapper.tpp new file mode 100644 index 0000000..7efefc4 --- /dev/null +++ b/src/DI/object_wrapper.tpp @@ -0,0 +1,9 @@ +#pragma once + +#include "object_wrapper.hpp" + +template <class Interface, class ObjectImpl> +std::shared_ptr<Interface> ObjectWrapper<Interface, ObjectImpl>::get() const +{ + return ObjectImpl::resolve(_container); +} diff --git a/src/argument_parser.cpp b/src/argument_parser.cpp new file mode 100644 index 0000000..b5f14bc --- /dev/null +++ b/src/argument_parser.cpp @@ -0,0 +1,100 @@ +#include "argument_parser.hpp" + +#include "conversion.hpp" +#include "interfaces/randomization.hpp" + +#include <cstdlib> +#include <iostream> +#include <string_view> + +namespace +{ +void optarg_error(char arg, const std::string_view &error) +{ + std::cout << "Error: Invalid option argument for -" << arg << ". " << error + << std::endl; + exit(EXIT_FAILURE); +} + +/** + * Returns the current optarg as a string view. + */ +std::string_view get_str_optarg() +{ + return std::string_view(optarg); +} + +/** + * Returns the current optarg as a unsigned integer. + * + * @param arg The current command-line argument character + * @param check_zero Whether or not to make sure that the result is not zero + */ +unsigned int get_uint_optarg(char arg, bool check_zero = false) +{ + auto conversion_result = str_to_uint(get_str_optarg()); + + if (!conversion_result.success || (check_zero && conversion_result.result == 0)) + { + optarg_error(arg, conversion_result.fail_reason); + } + + return conversion_result.result; +} +} // namespace + +ArgumentParser::ArgumentParser( + IRandomNumberGeneratorFactory random_number_generator_factory) + : _random_number_generator_factory(std::move(random_number_generator_factory)) +{ +} + +ParsedArguments +ArgumentParser::parse(const std::vector<option> &options, + const std::string_view &short_options, const int &argc, + char *const *argv) // NOLINT(cppcoreguidelines-avoid-c-arrays, + // modernize-avoid-c-arrays) +{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + const auto args = std::vector<std::string_view>(argv, argv + argc); + + const auto program_name = args[0]; + + ParsedArguments parsed_arguments; + + char arg = 0; + while ((arg = static_cast<char>(getopt_long(argc, argv, short_options.data(), + options.data(), nullptr))) != -1) + { + switch (arg) + { + case 's': + { + auto seed = get_uint_optarg(arg, true); + + parsed_arguments.random_gen = _random_number_generator_factory(seed); + break; + } + case 'h': + { + std::cout << "Usage: " << program_name + << " [OPTION]...\n\n" + "Options:\n" + << " -s, --seed SEED The randomization seed used\n" + " -h --help Displays usage information" + << std::endl; + exit(EXIT_SUCCESS); + } + case '?': + { + std::cout << "\nTry '" << program_name << " --help' for more information" + << std::endl; + exit(EXIT_FAILURE); + } + default: + abort(); + } + } + + return parsed_arguments; +} diff --git a/src/argument_parser.hpp b/src/argument_parser.hpp new file mode 100644 index 0000000..0bcaeb5 --- /dev/null +++ b/src/argument_parser.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "DI/auto_wirable.hpp" +#include "interfaces/argument_parser.hpp" +#include "interfaces/randomization.hpp" + +#include <getopt.h> +#include <string_view> +#include <vector> + +class ArgumentParser + : public IArgumentParser, + public AutoWirable<IArgumentParser, ArgumentParser, IRandomNumberGeneratorFactory> +{ +public: + explicit ArgumentParser( + IRandomNumberGeneratorFactory random_number_generator_factory); + + ParsedArguments + parse(const std::vector<option> &options, const std::string_view &short_options, + const int &argc, + char *const *argv) override; // NOLINT(cppcoreguidelines-avoid-c-arrays, + // modernize-avoid-c-arrays) + +private: + IRandomNumberGeneratorFactory _random_number_generator_factory; +}; diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp new file mode 100644 index 0000000..85498bc --- /dev/null +++ b/src/bootstrap.cpp @@ -0,0 +1,36 @@ +#include "bootstrap.hpp" + +// Interfaces +#include "interfaces/argument_parser.hpp" +#include "interfaces/randomization.hpp" + +// Implementations +#include "argument_parser.hpp" +#include "randomization/generator.hpp" +#include "randomization/seed_generator.hpp" + +#include <memory> +#include <random> + +Container bootstrap() +{ + auto container = Container(); + + container.bind<IArgumentParser>().to<ArgumentParser>(); + + container.bind<IRandomNumberGeneratorFactory>().to_factory( + [](const unsigned int &seed) + { + return std::dynamic_pointer_cast<IRandomNumberGenerator>( + std::make_shared<RandomNumberGenerator>(seed)); + }); + + container.bind<ISeedGeneratorFactory>().to_factory( + []() + { + return std::dynamic_pointer_cast<ISeedGenerator>( + std::make_shared<SeedGenerator>(std::make_unique<std::random_device>())); + }); + + return container; +} diff --git a/src/bootstrap.hpp b/src/bootstrap.hpp new file mode 100644 index 0000000..a822017 --- /dev/null +++ b/src/bootstrap.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include "DI/container.hpp" + +Container bootstrap(); diff --git a/src/game_of_life.cpp b/src/game_of_life.cpp index 3cd662b..9f7b019 100644 --- a/src/game_of_life.cpp +++ b/src/game_of_life.cpp @@ -1,94 +1,29 @@ -#include "conversion.hpp" -#include "randomization.hpp" +#include "bootstrap.hpp" +#include "interfaces/argument_parser.hpp" +#include "interfaces/randomization.hpp" #include <getopt.h> -#include <iostream> -#include <memory> -#include <string_view> #include <vector> -namespace -{ -void optarg_error(char arg, const std::string_view &error) -{ - std::cout << "Error: Invalid option argument for -" << arg << ". " << error - << std::endl; - exit(EXIT_FAILURE); -} - -/** - * Returns the current optarg as a string view. - */ -std::string_view get_str_optarg() -{ - return std::string_view(optarg); -} - -/** - * Returns the current optarg as a unsigned integer. - * - * @param arg The current command-line argument character - * @param check_zero Whether or not to make sure that the result is not zero - */ -unsigned int get_uint_optarg(char arg, bool check_zero = false) -{ - auto conversion_result = str_to_uint(get_str_optarg()); - - if (!conversion_result.success || (check_zero && conversion_result.result == 0)) - { - optarg_error(arg, conversion_result.fail_reason); - } - - return conversion_result.result; -} -} // namespace - -constexpr std::array<option, 8> options = { - option({"seed", required_argument, nullptr, 's'}), - option({"help", no_argument, nullptr, 0}), option({nullptr, 0, nullptr, 0})}; +const std::vector<option> options = {option({"seed", required_argument, nullptr, 's'}), + option({"help", no_argument, nullptr, 'h'}), + option({nullptr, 0, nullptr, 0})}; int main(int argc, char *argv[]) { - auto args = std::vector<std::string_view>(argv, argv + argc); + auto container = bootstrap(); - std::shared_ptr<RandomNumberGenerator> random_gen = nullptr; + auto argument_parser = container.get<IArgumentParser>(); - char arg = 0; - while ((arg = static_cast<char>( - getopt_long(argc, argv, "s:", options.data(), nullptr))) != -1) - { - switch (arg) - { - case 's': - { - auto seed = get_uint_optarg(arg, true); - - random_gen = std::make_shared<RandomNumberGenerator>(seed); - break; - } - case 0: - { - std::cout << "Usage: " << args[0] - << " [OPTION]...\n\n" - "Options:\n" - << " -s, --seed SEED The randomization seed used\n" - " --help Displays usage information" - << std::endl; - return EXIT_SUCCESS; - } - case '?': - { - std::cout << "\nTry '" << args[0] << " --help' for more information" - << std::endl; - return EXIT_FAILURE; - } - default: - abort(); - } - } + auto parsed_arguments = argument_parser->parse(options, "s:h", argc, argv); - if (random_gen == nullptr) + if (parsed_arguments.random_gen == nullptr) { - random_gen = std::make_shared<RandomNumberGenerator>(); + auto seed_generator_factory = container.get<ISeedGeneratorFactory>(); + auto random_number_generator_factory = + container.get<IRandomNumberGeneratorFactory>(); + + parsed_arguments.random_gen = + random_number_generator_factory(seed_generator_factory()->random_seed()); } } diff --git a/src/interfaces/argument_parser.hpp b/src/interfaces/argument_parser.hpp new file mode 100644 index 0000000..222d9e0 --- /dev/null +++ b/src/interfaces/argument_parser.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "interfaces/randomization.hpp" + +#include <getopt.h> +#include <memory> +#include <string_view> +#include <vector> + +struct ParsedArguments +{ + std::shared_ptr<IRandomNumberGenerator> random_gen = nullptr; +}; + +class IArgumentParser +{ +public: + virtual ParsedArguments + parse(const std::vector<option> &options, const std::string_view &short_options, + const int &argc, + char *const *argv) = 0; // NOLINT(cppcoreguidelines-avoid-c-arrays, + // modernize-avoid-c-arrays) +}; diff --git a/src/interfaces/randomization.hpp b/src/interfaces/randomization.hpp new file mode 100644 index 0000000..78456a2 --- /dev/null +++ b/src/interfaces/randomization.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include <functional> +#include <memory> + +class ISeedGenerator +{ +public: + [[nodiscard]] virtual unsigned int random_seed() const = 0; +}; + +using ISeedGeneratorFactory = std::function<std::shared_ptr<ISeedGenerator>()>; + +/** + * Pseudo-random unsigned integer generator. + */ +class IRandomNumberGenerator +{ +public: + /** + * Returns a number in the range of a to b. + * + * @param a A number lower than b + * @param b A number greater than a + */ + [[nodiscard]] virtual unsigned int in_range(const unsigned int &a, + const unsigned int &b) const = 0; +}; + +using IRandomNumberGeneratorFactory = + std::function<std::shared_ptr<IRandomNumberGenerator>(const unsigned int &seed)>; diff --git a/src/randomization.hpp b/src/randomization.hpp deleted file mode 100644 index b4931d7..0000000 --- a/src/randomization.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <memory> -#include <random> - -/** - * Pseudo-random unsigned integer generator. - */ -class RandomNumberGenerator -{ -public: - /** - * Creates a pseudo-random number generator. - * - * @param seed A number generation seed - */ - explicit RandomNumberGenerator(const unsigned int &seed); - - /** - * Creates a pesudo-random number generator. - */ - RandomNumberGenerator(); - - /** - * Generates a number in the range of a to b. - * - * @param a A number lower than b - * @param b A number greater than a - */ - [[nodiscard]] unsigned int in_range(const unsigned int &a, - const unsigned int &b) const; - -private: - std::unique_ptr<std::mt19937> _generator; -}; diff --git a/src/randomization.cpp b/src/randomization/generator.cpp index 8f233d2..b9bcb8a 100644 --- a/src/randomization.cpp +++ b/src/randomization/generator.cpp @@ -1,17 +1,10 @@ -#include "randomization.hpp" +#include "generator.hpp" RandomNumberGenerator::RandomNumberGenerator(const unsigned int &seed) { this->_generator = std::make_unique<std::mt19937>(seed); } -RandomNumberGenerator::RandomNumberGenerator() -{ - std::random_device random_device; - - this->_generator = std::make_unique<std::mt19937>(random_device()); -} - unsigned int RandomNumberGenerator::in_range(const unsigned int &a, const unsigned int &b) const { diff --git a/src/randomization/generator.hpp b/src/randomization/generator.hpp new file mode 100644 index 0000000..3acfc98 --- /dev/null +++ b/src/randomization/generator.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "interfaces/randomization.hpp" + +#include <memory> +#include <random> + +class RandomNumberGenerator : public IRandomNumberGenerator +{ +public: + explicit RandomNumberGenerator(const unsigned int &seed); + + [[nodiscard]] unsigned int in_range(const unsigned int &a, + const unsigned int &b) const override; + +private: + std::unique_ptr<std::mt19937> _generator; +}; diff --git a/src/randomization/seed_generator.cpp b/src/randomization/seed_generator.cpp new file mode 100644 index 0000000..fdb2b12 --- /dev/null +++ b/src/randomization/seed_generator.cpp @@ -0,0 +1,11 @@ +#include "seed_generator.hpp" + +SeedGenerator::SeedGenerator(const std::shared_ptr<std::random_device> &random_device) + : _random_device(random_device) +{ +} + +unsigned int SeedGenerator::random_seed() const +{ + return (*_random_device)(); +} diff --git a/src/randomization/seed_generator.hpp b/src/randomization/seed_generator.hpp new file mode 100644 index 0000000..238fdbe --- /dev/null +++ b/src/randomization/seed_generator.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "interfaces/randomization.hpp" + +#include <memory> +#include <random> + +class SeedGenerator : public ISeedGenerator +{ +public: + explicit SeedGenerator(const std::shared_ptr<std::random_device> &random_device); + + [[nodiscard]] unsigned int random_seed() const override; + +private: + const std::shared_ptr<std::random_device> &_random_device; +}; |