Skip to content

Commit

Permalink
Fix concepts.
Browse files Browse the repository at this point in the history
  • Loading branch information
lhruby committed Oct 1, 2024
1 parent 254e892 commit 8db1ea1
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 37 deletions.
49 changes: 13 additions & 36 deletions modules/random/include/hephaestus/random/random_object_creator.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@
#include <fmt/format.h>
#include <magic_enum.hpp>

#include "hephaestus/utils/concepts.h"
#include "hephaestus/utils/exception.h"

namespace heph::random {

//=================================================================================================
// Random boolean creation
//=================================================================================================
template <typename T>
concept IsBoolean = std::is_same_v<T, bool>;

template <IsBoolean T>
template <BooleanType T>
[[nodiscard]] auto random(std::mt19937_64& mt) -> T {
std::bernoulli_distribution dist;
return dist(mt);
Expand All @@ -34,9 +32,9 @@ template <IsBoolean T>
// Random integer value creation
//=================================================================================================
template <typename T>
concept IsNonBooleanIntegral = std::integral<T> && !std::same_as<T, bool>;
concept NonBooleanIntegralType = std::integral<T> && !BooleanType<T>;

template <IsNonBooleanIntegral T>
template <NonBooleanIntegralType T>
[[nodiscard]] auto random(std::mt19937_64& mt) -> T {
std::uniform_int_distribution<T> dist;
return dist(mt);
Expand All @@ -54,10 +52,7 @@ template <std::floating_point T>
//=================================================================================================
// Random enum creation
//=================================================================================================
template <typename T>
concept IsEnum = std::is_enum_v<T>;

template <IsEnum T>
template <EnumType T>
[[nodiscard]] auto random(std::mt19937_64& mt) -> T {
static const auto enum_values = magic_enum::enum_values<T>();
std::uniform_int_distribution<size_t> dist(0, enum_values.size() - 1);
Expand All @@ -67,17 +62,8 @@ template <IsEnum T>
//=================================================================================================
// Random timestamp creation
//=================================================================================================
template <typename T>
concept IsTimestamp = requires {
typename T::clock;
typename T::duration;
requires std::is_same_v<typename T::clock, std::chrono::system_clock> ||
std::is_same_v<typename T::clock, std::chrono::steady_clock>;
requires std::is_same_v<T, typename std::chrono::time_point<typename T::clock, typename T::duration>>;
};

namespace internal {
template <IsTimestamp T, size_t Year>
template <ChronoTimestampType T, size_t Year>
[[nodiscard]] constexpr auto createFinalTimestampOfTheYear() -> T {
// The final date of the year is YYYY-12-31.
constexpr auto YEAR = std::chrono::year{ Year };
Expand All @@ -95,7 +81,7 @@ template <IsTimestamp T, size_t Year>
} // namespace internal

/// Create a random timestamp between year 1970 and the year 2100.
template <IsTimestamp T>
template <ChronoTimestampType T>
[[nodiscard]] auto random(std::mt19937_64& mt) -> T {
static constexpr auto MIN_DURATION = 0; // Start of UNIX epoch time == year 1970.
static constexpr auto MAX_YEAR = 2100;
Expand All @@ -113,11 +99,11 @@ template <IsTimestamp T>
// Random struct/class creation
//=================================================================================================
template <class T>
concept HasrandomMethod = requires(std::mt19937_64& mt) {
concept HasRandomMethod = requires(std::mt19937_64& mt) {
{ T::random(mt) } -> std::convertible_to<T>;
};

template <HasrandomMethod T>
template <HasRandomMethod T>
[[nodiscard]] auto random(std::mt19937_64& mt) -> T {
return T::random(mt);
}
Expand All @@ -126,7 +112,7 @@ template <HasrandomMethod T>
// Concept for random creatable types
//=================================================================================================
template <class T>
concept IsRandomCreatable = requires(std::mt19937_64& mt) {
concept RandomCreatable = requires(std::mt19937_64& mt) {
{ random<T>(mt) } -> std::convertible_to<T>;
};

Expand Down Expand Up @@ -154,11 +140,8 @@ namespace internal {
//=================================================================================================
// Random string creation
//=================================================================================================
template <typename T>
concept IsString = std::same_as<T, std::string>;

/// Generate a random string of characters, including special case characters and numbers.
template <IsString T>
template <StringType T>
[[nodiscard]] auto random(std::mt19937_64& mt, std::optional<size_t> fixed_size = std::nullopt,
bool allow_empty = true) -> T {
const auto size = internal::getSize(mt, fixed_size, allow_empty);
Expand All @@ -179,17 +162,11 @@ template <IsString T>
//=================================================================================================
// Random vector creation
//=================================================================================================
namespace internal {
template <typename T>
concept IsVector =
requires { typename T::value_type; } && (std::is_same_v<T, std::vector<typename T::value_type>>);
} // namespace internal

template <typename T>
concept IsRandomCreatableVector = internal::IsVector<T> && IsRandomCreatable<typename T::value_type>;
concept RandomCreatableVector = VectorType<T> && RandomCreatable<typename T::value_type>;

/// Fill a vector with randomly generated values of type T.
template <IsRandomCreatableVector T>
template <RandomCreatableVector T>
[[nodiscard]] auto random(std::mt19937_64& mt, std::optional<size_t> fixed_size = std::nullopt,
bool allow_empty = true) -> T {
const auto size = internal::getSize(mt, fixed_size, allow_empty);
Expand Down
2 changes: 1 addition & 1 deletion modules/random/tests/random_object_creator_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ TYPED_TEST(RandomTypeTests, RandomnessTest) {
// case, as it is already included in testing for randomness. Repeadedly creating an empty container would
// fail the RandomnessTest.
TYPED_TEST(RandomTypeTests, ContainerSizeTest) {
if constexpr (IsRandomCreatableVector<TypeParam> || IsString<TypeParam>) {
if constexpr (RandomCreatableVector<TypeParam> || StringType<TypeParam>) {
auto mt = createRNG();

static constexpr std::size_t SIZE_ZERO = 0;
Expand Down
28 changes: 28 additions & 0 deletions modules/utils/include/hephaestus/utils/concepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ concept ScalarType = std::is_scalar_v<T>;
template <typename T>
concept EnumType = std::is_enum_v<T>;

template <typename T>
concept BooleanType = std::is_same_v<T, bool>;

template <typename T>
concept StringType = std::is_same_v<T, std::string>;

template <typename T>
concept ArrayType = requires {
typename T::value_type;
Expand Down Expand Up @@ -47,6 +53,28 @@ concept ChronoSystemClockType = std::is_same_v<T, std::chrono::system_clock>;
template <typename T>
concept ChronoSteadyClockType = std::is_same_v<T, std::chrono::steady_clock>;

template <typename T>
concept ChronoClock = ChronoSystemClockType<T> || ChronoSteadyClockType<T>;

template <typename T>
concept ChronoSystemClockTimestampType = requires {
typename T::clock;
typename T::duration;
requires std::is_same_v<typename T::clock, std::chrono::system_clock>;
requires std::is_same_v<T, typename std::chrono::time_point<typename T::clock, typename T::duration>>;
};

template <typename T>
concept ChronoSteadyClockTimestampType = requires {
typename T::clock;
typename T::duration;
requires std::is_same_v<typename T::clock, std::chrono::steady_clock>;
requires std::is_same_v<T, typename std::chrono::time_point<typename T::clock, typename T::duration>>;
};

template <typename T>
concept ChronoTimestampType = ChronoSystemClockTimestampType<T> || ChronoSteadyClockTimestampType<T>;

template <typename T>
concept NumericType = (std::integral<T> || std::floating_point<T>)&&!std::same_as<T, bool>;

Expand Down

0 comments on commit 8db1ea1

Please sign in to comment.