From 05346a44ad5a169be669ccf54604bc46ac9e92f0 Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:34:34 +0000 Subject: [PATCH 1/4] :sparkles: make format.sh an executable --- format.sh | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 format.sh diff --git a/format.sh b/format.sh old mode 100644 new mode 100755 index d26dc5c8..704e3bce --- a/format.sh +++ b/format.sh @@ -1 +1,3 @@ +#!/bin/bash + find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\|h\)' -exec clang-format -style=file -i {} \; From b193b30f36f426690f723f1bda69aa02676c610d Mon Sep 17 00:00:00 2001 From: YousefEZ <45167695+YousefEZ@users.noreply.github.com> Date: Sat, 9 Mar 2024 18:34:40 +0000 Subject: [PATCH 2/4] :art: format the files --- libs/dummy_congestion_policy.h | 2 - libs/frr_queue.h | 98 +- libs/lfa_policy.h | 19 +- libs/modulo_congestion_policy.h | 14 +- libs/random/random.hpp | 2788 ++++++++++++++++--------------- libs/random_congestion_policy.h | 21 +- src/lfa.cc | 47 +- src/lfa_random.cc | 63 +- src/simple_dumbbell_topo.cc | 173 +- 9 files changed, 1662 insertions(+), 1563 deletions(-) diff --git a/libs/dummy_congestion_policy.h b/libs/dummy_congestion_policy.h index 3838f275..907abbb1 100644 --- a/libs/dummy_congestion_policy.h +++ b/libs/dummy_congestion_policy.h @@ -13,14 +13,12 @@ class DummyCongestionPolicy static bool isCongested(ns3::Queue* queue); }; - bool DummyCongestionPolicy::isCongested(ns3::Queue* queue) { // Placeholder for congestion detection return false; } - } // namespace ns3 #endif diff --git a/libs/frr_queue.h b/libs/frr_queue.h index 15bea576..ac7c6765 100644 --- a/libs/frr_queue.h +++ b/libs/frr_queue.h @@ -21,49 +21,45 @@ namespace ns3 template class FRRQueue : public Queue { - private: - + private: using Queue::GetContainer; using Queue::DoEnqueue; using Queue::DoDequeue; using Queue::DoRemove; using Queue::DoPeek; - + NS_LOG_TEMPLATE_DECLARE; - void ForwardToAlternateTarget(Ptr packet); static std::string makeQueueString(); + protected: - virtual bool Enqueue(Ptr p) override; + virtual bool Enqueue(Ptr p) override; virtual Ptr Dequeue() override; virtual Ptr Remove(void) override; virtual Ptr Peek() const override; + public: - FRR_POLICY m_frrPolicy; CONGESTION_POLICY m_congestionPolicy; - + static TypeId GetTypeId(); FRRQueue(); ~FRRQueue(); - + template void addAlternateTargets(DEVICES&&... devices); static const std::string& getQueueString(); }; - template FRRQueue::FRRQueue() - : Queue(), - NS_LOG_TEMPLATE_DEFINE("FRRQueue") + : Queue(), NS_LOG_TEMPLATE_DEFINE("FRRQueue") { NS_LOG_FUNCTION(this); } - template FRRQueue::~FRRQueue() { @@ -73,102 +69,106 @@ FRRQueue::~FRRQueue() template TypeId FRRQueue::GetTypeId() { - static TypeId tid = TypeId(getQueueString()) - .SetParent>() - .SetGroupName("Network") - .template AddConstructor>() - .AddAttribute("MaxSize", - "The max queue size", - QueueSizeValue(QueueSize("100p")), - MakeQueueSizeAccessor(&QueueBase::SetMaxSize, &QueueBase::GetMaxSize), - MakeQueueSizeChecker()); + static TypeId tid = + TypeId(getQueueString()) + .SetParent>() + .SetGroupName("Network") + .template AddConstructor>() + .AddAttribute("MaxSize", "The max queue size", + QueueSizeValue(QueueSize("100p")), + MakeQueueSizeAccessor(&QueueBase::SetMaxSize, + &QueueBase::GetMaxSize), + MakeQueueSizeChecker()); return tid; } - - template bool FRRQueue::Enqueue(Ptr packet) { NS_LOG_FUNCTION(this << packet); - if (m_congestionPolicy.isCongested(GetContainer())) - { + if (m_congestionPolicy.isCongested(GetContainer())) { NS_LOG_LOGIC("Congested Route, Rerouting packet: " << packet); ForwardToAlternateTarget(packet); NS_LOG_LOGIC("Rerouting complete"); - return false; + return false; } - NS_LOG_LOGIC("Enqueued " << packet << " to " << GetContainer().size() << " packets in queue."); + NS_LOG_LOGIC("Enqueued " << packet << " to " << GetContainer().size() + << " packets in queue."); DoEnqueue(GetContainer().end(), packet); return true; } - + template Ptr FRRQueue::Dequeue() { NS_LOG_FUNCTION(this); - + Ptr packet = DoDequeue(GetContainer().begin()); - + NS_LOG_LOGIC("Popped " << packet); return packet; } - + template Ptr FRRQueue::Remove() { NS_LOG_FUNCTION(this); - + Ptr packet = DoRemove(GetContainer().begin()); - + NS_LOG_LOGIC("Removed " << packet); - + return packet; } - + template Ptr FRRQueue::Peek() const { NS_LOG_FUNCTION(this); - + return DoPeek(GetContainer().begin()); } - template -void FRRQueue::ForwardToAlternateTarget(Ptr packet) +void FRRQueue::ForwardToAlternateTarget( + Ptr packet) { - auto alternativeTarget = m_frrPolicy.selectAlternativeTarget(); - alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); + auto alternativeTarget = m_frrPolicy.selectAlternativeTarget(); + alternativeTarget->Send(packet, alternativeTarget->GetAddress(), 0x0800); } template template -void FRRQueue::addAlternateTargets(DEVICES&&... devices) +void FRRQueue::addAlternateTargets( + DEVICES&&... devices) { - m_frrPolicy.addAlternateTargets(std::forward(devices)...); + m_frrPolicy.addAlternateTargets(std::forward(devices)...); } template std::string FRRQueue::makeQueueString() { - using QueueType = FRRQueue; + using QueueType = FRRQueue; int status; - char* demangled = abi::__cxa_demangle(STRINGIFY_TYPE_ALIAS(QueueType), nullptr, nullptr, &status); - std::string result = (status == 0 && demangled != nullptr) ? demangled : STRINGIFY_TYPE_ALIAS(QueueType); - free(demangled); + char* demangled = abi::__cxa_demangle(STRINGIFY_TYPE_ALIAS(QueueType), + nullptr, nullptr, &status); + std::string result = (status == 0 && demangled != nullptr) + ? demangled + : STRINGIFY_TYPE_ALIAS(QueueType); + free(demangled); return result; } template const std::string& FRRQueue::getQueueString() { - const static std::string result = FRRQueue::makeQueueString(); - return result; + const static std::string result = + FRRQueue::makeQueueString(); + return result; } NS_LOG_COMPONENT_DEFINE("FRRQueue"); } // namespace ns3 -#endif +#endif diff --git a/libs/lfa_policy.h b/libs/lfa_policy.h index e7adb2f9..3c59b4c7 100644 --- a/libs/lfa_policy.h +++ b/libs/lfa_policy.h @@ -13,35 +13,32 @@ namespace ns3 class LFAPolicy { - private: + private: std::list> m_alternateTargets; public: LFAPolicy() = default; - + template void addAlternateTargets(DEVICES&&... devices); ns3::Ptr selectAlternativeTarget(); }; - template void LFAPolicy::addAlternateTargets(DEVICES&&... devices) { - (m_alternateTargets.push_back(std::forward(devices)), ...); + (m_alternateTargets.push_back(std::forward(devices)), ...); } ns3::Ptr LFAPolicy::selectAlternativeTarget() { - if (m_alternateTargets.empty()) - { - return nullptr; - } - return m_alternateTargets.front(); + if (m_alternateTargets.empty()) { + return nullptr; + } + return m_alternateTargets.front(); } - } // namespace ns3 - + #endif diff --git a/libs/modulo_congestion_policy.h b/libs/modulo_congestion_policy.h index 561f4f75..b39be810 100644 --- a/libs/modulo_congestion_policy.h +++ b/libs/modulo_congestion_policy.h @@ -1,31 +1,25 @@ #ifndef MODULO_CONGESTION_POLICY_H #define MODULO_CONGESTION_POLICY_H - - template class ModuloCongestionPolicy { private: - int counter; + int counter; public: - template bool isCongested(const CONTAINER& container) { - increment(); - return counter; + increment(); + return counter; } - void increment() { - counter = (counter + 1) % MODULO; + counter = (counter + 1) % MODULO; } - }; - #endif diff --git a/libs/random/random.hpp b/libs/random/random.hpp index 80ce8816..08f5427a 100644 --- a/libs/random/random.hpp +++ b/libs/random/random.hpp @@ -36,1460 +36,1524 @@ SOFTWARE. #include #include #include -#include // std::forward, std::declval +#include // std::forward, std::declval #include // std::shuffle, std::next, std::distance -#include // std::begin, std::end, std::iterator_traits -#include // std::numeric_limits +#include // std::begin, std::end, std::iterator_traits +#include // std::numeric_limits #include #include -namespace effolkronium { - - namespace details { - /// Key type for getting common type numbers or objects - struct common{ }; - - /// Key type for weighted random number generation - struct weight{ }; - - /// True if type T is applicable by a std::uniform_int_distribution - template - struct is_uniform_int { - static constexpr bool value = - std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value; - }; - - /// True if type T is applicable by a std::uniform_real_distribution - template - struct is_uniform_real { - static constexpr bool value = - std::is_same::value - || std::is_same::value - || std::is_same::value; - }; - - /// True if type T is plain byte - template - struct is_byte { - static constexpr bool value = - std::is_same::value - || std::is_same::value; - }; - - /// True if type T is plain number type - template - struct is_supported_number { - static constexpr bool value = - is_byte ::value - || is_uniform_real::value - || is_uniform_int ::value; - }; - - /// True if type T is character type - template - struct is_supported_character { - static constexpr bool value = - std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value; - }; - - /// True if type T is iterator - template - struct is_iterator { - private: - static char test( ... ); - - template ::difference_type, - typename = typename std::iterator_traits::pointer, - typename = typename std::iterator_traits::reference, - typename = typename std::iterator_traits::value_type, - typename = typename std::iterator_traits::iterator_category - > static long test( U&& ); - public: - static constexpr bool value = std::is_same< - decltype( test( std::declval( ) ) ), long>::value; - }; - - template - class has_reserve - { - private: - template - static char test(...); - - template - static long test(decltype(&C::reserve)); - public: - static constexpr bool value = std::is_same< - decltype(test(0)), long>::value; - }; - - template - class has_insert - { - private: - template - static char test(...); - - template - static long test(decltype(&C::insert)); - public: - static constexpr bool value = std::is_same< - decltype(test(0)), long>::value; - }; - - template - using void_t = void; - - template - struct is_map : public std::false_type {}; - - template - struct is_map> : public std::true_type{}; - - } // namespace details - - /// Default seeder for 'random' classes - struct seeder_default { - /// return seed sequence - std::seed_seq& operator() ( ) { - // MinGW issue, std::random_device returns constant value - // Use std::seed_seq with additional seed from C++ chrono - return seed_seq; - } - private: - std::seed_seq seed_seq{ { - static_cast( std::random_device{ }( ) ), - static_cast( std::chrono::steady_clock::now( ) - .time_since_epoch( ).count( ) ), - } }; - }; +namespace effolkronium +{ + +namespace details +{ +/// Key type for getting common type numbers or objects +struct common { +}; + +/// Key type for weighted random number generation +struct weight { +}; + +/// True if type T is applicable by a std::uniform_int_distribution +template +struct is_uniform_int { + static constexpr bool value = + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; + +/// True if type T is applicable by a std::uniform_real_distribution +template +struct is_uniform_real { + static constexpr bool value = std::is_same::value || + std::is_same::value || + std::is_same::value; +}; + +/// True if type T is plain byte +template +struct is_byte { + static constexpr bool value = std::is_same::value || + std::is_same::value; +}; + +/// True if type T is plain number type +template +struct is_supported_number { + static constexpr bool value = is_byte::value || + is_uniform_real::value || + is_uniform_int::value; +}; + +/// True if type T is character type +template +struct is_supported_character { + static constexpr bool value = + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value; +}; + +/// True if type T is iterator +template +struct is_iterator { + private: + static char test(...); + + template ::difference_type, + typename = typename std::iterator_traits::pointer, + typename = typename std::iterator_traits::reference, + typename = typename std::iterator_traits::value_type, + typename = typename std::iterator_traits::iterator_category> + static long test(U&&); + + public: + static constexpr bool value = + std::is_same())), long>::value; +}; + +template +class has_reserve +{ + private: + template + static char test(...); + + template + static long test(decltype(&C::reserve)); + + public: + static constexpr bool value = + std::is_same(0)), long>::value; +}; + +template +class has_insert +{ + private: + template + static char test(...); + + template + static long test(decltype(&C::insert)); + + public: + static constexpr bool value = + std::is_same(0)), long>::value; +}; + +template +using void_t = void; + +template +struct is_map : public std::false_type { +}; + +template +struct is_map> : public std::true_type { +}; + +} // namespace details + +/// Default seeder for 'random' classes +struct seeder_default { + /// return seed sequence + std::seed_seq& operator()() + { + // MinGW issue, std::random_device returns constant value + // Use std::seed_seq with additional seed from C++ chrono + return seed_seq; + } + + private: + std::seed_seq seed_seq{{ + static_cast(std::random_device{}()), + static_cast( + std::chrono::steady_clock::now().time_since_epoch().count()), + }}; +}; + +/** + * \brief Base template class for random + * with static API and static internal member storage + * \note it is NOT thread safe but more efficient then + * basic_random_thread_local + * \param Engine A random engine with interface like in the std::mt19937 + * \param Seeder A seeder type which return seed for internal engine + * through operator() + */ +template class IntegerDist = std::uniform_int_distribution, + template class RealDist = std::uniform_real_distribution, + typename BoolDist = std::bernoulli_distribution> +class basic_random_base +{ + public: + /// Type of used random number engine + using engine_type = Engine; + + /// Type of used random number seeder + using seeder_type = Seeder; + + /// Type of used integer distribution + template + using integer_dist_t = IntegerDist; + + /// Type of used real distribution + template + using real_dist_t = RealDist; + + /// Type of used bool distribution + using bool_dist_t = BoolDist; + + /// Key type for getting common type numbers or objects + using common = details::common; + + /// Key type for weighted random number generation + using weight = details::weight; /** - * \brief Base template class for random - * with static API and static internal member storage - * \note it is NOT thread safe but more efficient then - * basic_random_thread_local - * \param Engine A random engine with interface like in the std::mt19937 - * \param Seeder A seeder type which return seed for internal engine - * through operator() - */ - template< - typename Derived, - typename Engine, - typename Seeder = seeder_default, - template class IntegerDist = std::uniform_int_distribution, - template class RealDist = std::uniform_real_distribution, - typename BoolDist = std::bernoulli_distribution - > - class basic_random_base { - public: - /// Type of used random number engine - using engine_type = Engine; - - /// Type of used random number seeder - using seeder_type = Seeder; - - /// Type of used integer distribution - template - using integer_dist_t = IntegerDist; - - /// Type of used real distribution - template - using real_dist_t = RealDist; - - /// Type of used bool distribution - using bool_dist_t = BoolDist; - - /// Key type for getting common type numbers or objects - using common = details::common; - - /// Key type for weighted random number generation - using weight = details::weight; - - /** - * \return The minimum value - * potentially generated by the random-number engine - */ - static constexpr typename Engine::result_type (min)( ) { - return (Engine::min)( ); - } + * \return The minimum value + * potentially generated by the random-number engine + */ + static constexpr typename Engine::result_type(min)() + { + return (Engine::min)(); + } - /** - * \return The maximum value - * potentially generated by the random-number engine - */ - static constexpr typename Engine::result_type (max)( ) { - return (Engine::max)( ); - } - - /// Advances the internal state by z times - static void discard( const unsigned long long z ) { - engine_instance( ).discard( z ); - } - - /// Reseed by Seeder - static void reseed( ) { - Seeder seeder; - seed( seeder( ) ); - } - - /** - * \brief Reinitializes the internal state - * of the random-number engine using new seed value - * \param value The seed value to use - * in the initialization of the internal state - */ - static void seed( const typename Engine::result_type value = - Engine::default_seed ) { - engine_instance( ).seed( value ); - } + /** + * \return The maximum value + * potentially generated by the random-number engine + */ + static constexpr typename Engine::result_type(max)() + { + return (Engine::max)(); + } + + /// Advances the internal state by z times + static void discard(const unsigned long long z) + { + engine_instance().discard(z); + } + + /// Reseed by Seeder + static void reseed() + { + Seeder seeder; + seed(seeder()); + } - /** - * \brief Reinitializes the internal state - * of the random-number engine using new seed value - * \param seq The seed sequence - * to use in the initialization of the internal state - */ - template - static void seed( Sseq& seq ) { - engine_instance( ).seed( seq ); - } + /** + * \brief Reinitializes the internal state + * of the random-number engine using new seed value + * \param value The seed value to use + * in the initialization of the internal state + */ + static void + seed(const typename Engine::result_type value = Engine::default_seed) + { + engine_instance().seed(value); + } - /// return random number from engine in [min(), max()] range - static typename Engine::result_type get( ) { - return engine_instance( )( ); - } + /** + * \brief Reinitializes the internal state + * of the random-number engine using new seed value + * \param seq The seed sequence + * to use in the initialization of the internal state + */ + template + static void seed(Sseq& seq) + { + engine_instance().seed(seq); + } + + /// return random number from engine in [min(), max()] range + static typename Engine::result_type get() + { + return engine_instance()(); + } - /** - * \brief Compares internal pseudo-random number engine - * with 'other' pseudo-random number engine. - * Two engines are equal, if their internal states - * are equivalent, that is, if they would generate - * equivalent values for any number of calls of operator() - * \param other The engine, with which the internal engine will be compared - * \return true, if other and internal engine are equal - */ - static bool is_equal( const Engine& other ) { - return engine_instance( ) == other; - } + /** + * \brief Compares internal pseudo-random number engine + * with 'other' pseudo-random number engine. + * Two engines are equal, if their internal states + * are equivalent, that is, if they would generate + * equivalent values for any number of calls of operator() + * \param other The engine, with which the internal engine will be compared + * \return true, if other and internal engine are equal + */ + static bool is_equal(const Engine& other) + { + return engine_instance() == other; + } - /** - * \brief Serializes the internal state of the - * internal pseudo-random number engine as a sequence - * of decimal numbers separated by one or more spaces, - * and inserts it to the stream ost. The fill character - * and the formatting flags of the stream are - * ignored and unaffected. - * \param ost The output stream to insert the data to - */ - template - static void serialize( std::basic_ostream& ost ) { - ost << engine_instance( ); - } + /** + * \brief Serializes the internal state of the + * internal pseudo-random number engine as a sequence + * of decimal numbers separated by one or more spaces, + * and inserts it to the stream ost. The fill character + * and the formatting flags of the stream are + * ignored and unaffected. + * \param ost The output stream to insert the data to + */ + template + static void serialize(std::basic_ostream& ost) + { + ost << engine_instance(); + } - /** - * \brief Restores the internal state of the - * internal pseudo-random number engine from - * the serialized representation, which - * was created by an earlier call to 'serialize' - * using a stream with the same imbued locale and - * the same CharT and Traits. - * If the input cannot be deserialized, - * internal engine is left unchanged and failbit is raised on ist - * \param ost The input stream to extract the data from - */ - template - static void deserialize( std::basic_istream& ist ) { - ist >> engine_instance( ); - } + /** + * \brief Restores the internal state of the + * internal pseudo-random number engine from + * the serialized representation, which + * was created by an earlier call to 'serialize' + * using a stream with the same imbued locale and + * the same CharT and Traits. + * If the input cannot be deserialized, + * internal engine is left unchanged and failbit is raised on ist + * \param ost The input stream to extract the data from + */ + template + static void deserialize(std::basic_istream& ist) + { + ist >> engine_instance(); + } - /** - * \brief Generate a random integer number in a [from; to] range - * by std::uniform_int_distribution - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \return A random integer number in a [from; to] range - * \note Allow both: 'from' <= 'to' and 'from' >= 'to' - * \note Prevent implicit type conversion - */ - template - static typename std::enable_if::value - , T>::type get( T from = (std::numeric_limits::min)( ), - T to = (std::numeric_limits::max)( ) ) { - if( from < to ) // Allow range from higher to lower - return IntegerDist{ from, to }( engine_instance( ) ); - return IntegerDist{ to, from }( engine_instance( ) ); - } + /** + * \brief Generate a random integer number in a [from; to] range + * by std::uniform_int_distribution + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \return A random integer number in a [from; to] range + * \note Allow both: 'from' <= 'to' and 'from' >= 'to' + * \note Prevent implicit type conversion + */ + template + static typename std::enable_if::value, T>::type + get(T from = (std::numeric_limits::min)(), + T to = (std::numeric_limits::max)()) + { + if (from < to) // Allow range from higher to lower + return IntegerDist{from, to}(engine_instance()); + return IntegerDist{to, from}(engine_instance()); + } - /** - * \brief Generate a random real number in a [from; to] range - * by std::uniform_real_distribution - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \return A random real number in a [from; to] range - * \note Allow both: 'from' <= 'to' and 'from' >= 'to' - * \note Prevent implicit type conversion - */ - template - static typename std::enable_if::value - , T>::type get( T from = (std::numeric_limits::min)( ), - T to = (std::numeric_limits::max)( ) ) { - if( from < to ) // Allow range from higher to lower - return RealDist{ from, to }( engine_instance( ) ); - return RealDist{ to, from }( engine_instance( ) ); - } + /** + * \brief Generate a random real number in a [from; to] range + * by std::uniform_real_distribution + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \return A random real number in a [from; to] range + * \note Allow both: 'from' <= 'to' and 'from' >= 'to' + * \note Prevent implicit type conversion + */ + template + static typename std::enable_if::value, T>::type + get(T from = (std::numeric_limits::min)(), + T to = (std::numeric_limits::max)()) + { + if (from < to) // Allow range from higher to lower + return RealDist{from, to}(engine_instance()); + return RealDist{to, from}(engine_instance()); + } - /** - * \brief Generate a random byte number in a [from; to] range - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \return A random byte number in a [from; to] range - * \note Allow both: 'from' <= 'to' and 'from' >= 'to' - * \note Prevent implicit type conversion - */ - template - static typename std::enable_if::value - , T>::type get( T from = (std::numeric_limits::min)( ), - T to = (std::numeric_limits::max)( ) ) { - // Choose between short and unsigned short for byte conversion - using short_t = typename std::conditional::value, - short, unsigned short>::type; - - return static_cast( get( from, to ) ); - } + /** + * \brief Generate a random byte number in a [from; to] range + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \return A random byte number in a [from; to] range + * \note Allow both: 'from' <= 'to' and 'from' >= 'to' + * \note Prevent implicit type conversion + */ + template + static typename std::enable_if::value, T>::type + get(T from = (std::numeric_limits::min)(), + T to = (std::numeric_limits::max)()) + { + // Choose between short and unsigned short for byte conversion + using short_t = typename std::conditional::value, + short, unsigned short>::type; + + return static_cast(get(from, to)); + } - /** - * \brief Generate a random common_type number in a [from; to] range - * \param Key The Key type for this version of 'get' method - * Type should be '(THIS_TYPE)::common' struct - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \return A random common_type number in a [from; to] range - * \note Allow both: 'from' <= 'to' and 'from' >= 'to' - * \note Allow implicit type conversion - * \note Prevent implicit type conversion from signed to unsigned types - * Why? std::common_type chooses unsigned value, - * then Signed value will be converted to Unsigned value - * which gives us a wrong range for random values. - * https://stackoverflow.com/a/5416498/5734836 - */ - template< - typename Key, - typename A, - typename B, - typename C = typename std::common_type::type - > - static typename std::enable_if< - std::is_same::value - && details::is_supported_number::value - && details::is_supported_number::value + /** + * \brief Generate a random common_type number in a [from; to] range + * \param Key The Key type for this version of 'get' method + * Type should be '(THIS_TYPE)::common' struct + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \return A random common_type number in a [from; to] range + * \note Allow both: 'from' <= 'to' and 'from' >= 'to' + * \note Allow implicit type conversion + * \note Prevent implicit type conversion from signed to unsigned types + * Why? std::common_type chooses unsigned value, + * then Signed value will be converted to Unsigned value + * which gives us a wrong range for random values. + * https://stackoverflow.com/a/5416498/5734836 + */ + template ::type> + static typename std::enable_if< + std::is_same::value && + details::is_supported_number::value && + details::is_supported_number::value // Prevent implicit type conversion from signed to unsigned types - && std::is_signed::value != std::is_unsigned::value - , C>::type get( A from = (std::numeric_limits::min)( ), - B to = (std::numeric_limits::max)( ) ) { - return get( static_cast( from ), static_cast( to ) ); - } + && std::is_signed::value != std::is_unsigned::value, + C>::type + get(A from = (std::numeric_limits::min)(), + B to = (std::numeric_limits::max)()) + { + return get(static_cast(from), static_cast(to)); + } - /** - * \brief Generate a random character in a [from; to] range - * by std::uniform_int_distribution - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \return A random character in a [from; to] range - * \note Allow both: 'from' <= 'to' and 'from' >= 'to' - * \note Prevent implicit type conversion - */ - template - static typename std::enable_if::value - , T>::type get(T from = (std::numeric_limits::min)(), - T to = (std::numeric_limits::max)()) { - if (from < to) // Allow range from higher to lower - return static_cast(IntegerDist{ static_cast(from), static_cast(to) }(engine_instance())); - return static_cast(IntegerDist{ static_cast(to), static_cast(from) }(engine_instance())); - } + /** + * \brief Generate a random character in a [from; to] range + * by std::uniform_int_distribution + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \return A random character in a [from; to] range + * \note Allow both: 'from' <= 'to' and 'from' >= 'to' + * \note Prevent implicit type conversion + */ + template + static typename std::enable_if::value, + T>::type + get(T from = (std::numeric_limits::min)(), + T to = (std::numeric_limits::max)()) + { + if (from < to) // Allow range from higher to lower + return static_cast(IntegerDist{ + static_cast(from), + static_cast(to)}(engine_instance())); + return static_cast(IntegerDist{ + static_cast(to), + static_cast(from)}(engine_instance())); + } - /** - * \brief Generate a bool value with specific probability - * by std::bernoulli_distribution - * \param probability The probability of generating true in [0; 1] range - * 0 means always false, 1 means always true - * \return 'true' with 'probability' probability ('false' otherwise) - */ - template - static typename std::enable_if::value - , bool>::type get( const double probability = 0.5 ) { - assert( 0 <= probability && 1 >= probability ); // out of [0; 1] range - return BoolDist{ probability }( engine_instance( ) ); - } + /** + * \brief Generate a bool value with specific probability + * by std::bernoulli_distribution + * \param probability The probability of generating true in [0; 1] range + * 0 means always false, 1 means always true + * \return 'true' with 'probability' probability ('false' otherwise) + */ + template + static typename std::enable_if::value, bool>::type + get(const double probability = 0.5) + { + assert(0 <= probability && 1 >= probability); // out of [0; 1] range + return BoolDist{probability}(engine_instance()); + } - /** - * \brief Return random value from initializer_list - * \param init_list initializer_list with values - * \return Random value from initializer_list - * \note Should be 1 or more elements in initializer_list - * \note Warning! Elements in initializer_list can't be moved: - * https://stackoverflow.com/a/8193157/5734836 - */ - template - static T get( std::initializer_list init_list ) { - assert( 0u != init_list.size( ) ); - return *get( init_list.begin( ), init_list.end( ) ); - } + /** + * \brief Return random value from initializer_list + * \param init_list initializer_list with values + * \return Random value from initializer_list + * \note Should be 1 or more elements in initializer_list + * \note Warning! Elements in initializer_list can't be moved: + * https://stackoverflow.com/a/8193157/5734836 + */ + template + static T get(std::initializer_list init_list) + { + assert(0u != init_list.size()); + return *get(init_list.begin(), init_list.end()); + } - /** - * \brief Return random iterator from iterator range - * \param first, last - the range of elements - * \return Random iterator from [first, last) range - * \note If first == last, return last - */ - template - static typename std::enable_if::value - , InputIt>::type get( InputIt first, InputIt last ) { - const auto size = std::distance( first, last ); - if( 0 == size ) return last; - using diff_t = typename std::iterator_traits::difference_type; - return std::next( first, get( 0, size - 1 ) ); - } + /** + * \brief Return random iterator from iterator range + * \param first, last - the range of elements + * \return Random iterator from [first, last) range + * \note If first == last, return last + */ + template + static typename std::enable_if::value, + InputIt>::type + get(InputIt first, InputIt last) + { + const auto size = std::distance(first, last); + if (0 == size) return last; + using diff_t = typename std::iterator_traits::difference_type; + return std::next(first, get(0, size - 1)); + } - /** - * \brief Return random iterator from Container - * \param container The container with elements - * \return Random iterator from container - * \note If container is empty return std::end( container ) iterator - */ - template - static auto get( Container& container ) -> - typename std::enable_if::value - , decltype(std::begin(container)) - >::type { - return get( std::begin( container ), std::end( container ) ); - } + /** + * \brief Return random iterator from Container + * \param container The container with elements + * \return Random iterator from container + * \note If container is empty return std::end( container ) iterator + */ + template + static auto get(Container& container) -> typename std::enable_if< + details::is_iterator::value, + decltype(std::begin(container))>::type + { + return get(std::begin(container), std::end(container)); + } - /** - * \brief Return container filled with random values - * \param from The first limit number of a random range - * \param to The second limit number of a random range - * \param size The number of elements in resulting container - * \return Container filled with random values - * \note Container "reserve" method will be called before generation - */ - template class Container, typename A> - static typename std::enable_if< - details::has_reserve>::value - , Container>::type get(A from, A to, std::size_t size) { - Container container; - - container.reserve(size); - for (std::size_t i = 0; i < size; ++i) - container.insert(std::end(container), get(from, to)); - - return container; - } + /** + * \brief Return container filled with random values + * \param from The first limit number of a random range + * \param to The second limit number of a random range + * \param size The number of elements in resulting container + * \return Container filled with random values + * \note Container "reserve" method will be called before generation + */ + template