Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions include/dice/template-library/type_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,22 @@ namespace dice::template_library::type_list {
using filter_t = typename filter<TL, pred>::type;


/**
* Flatten a type list of type lists of types into a type list of types.
* @tparam TL type list of type lists
*/
template<typename TL>
struct flatten;

template<typename ...TLs>
struct flatten<type_list<TLs...>> {
Comment thread
nkaralis marked this conversation as resolved.
using type = concat_t<TLs...>;
};

template<typename TL>
using flatten_t = typename flatten<TL>::type;


namespace detail_generate {
template<typename IdxSeq, auto func>
struct generate_impl;
Expand Down Expand Up @@ -506,6 +522,25 @@ namespace dice::template_library::type_list {
using integer_sequence_to_type_list_t = typename integer_sequence_to_type_list<ISeq>::type;


/**
* Convert a tuple-like thing into a type list of its component types.
*/
template<typename Tuple>
struct tuple_to_type_list;

template<typename Tuple>
requires requires {
{ std::tuple_size_v<Tuple> } -> std::convertible_to<size_t>;
}
struct tuple_to_type_list<Tuple> {
using type = decltype([]<size_t... ixs>(std::index_sequence<ixs...>) {
return type_list<std::tuple_element_t<ixs, Tuple>...>{};
}(std::make_index_sequence<std::tuple_size_v<Tuple>>{}));
};

template<typename Tuple>
using tuple_to_type_list_t = typename tuple_to_type_list<Tuple>::type;

/**
* A marker type to indicate a failed operation
* when using opt
Expand Down
24 changes: 22 additions & 2 deletions include/dice/template-library/variant2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <compare>
#include <cstdint>
#include <exception>
#include <format>
#include <functional>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -720,7 +721,7 @@ namespace dice::template_library {
rhs = std::move(tmp);
}

constexpr bool operator==(variant2 const &other) const noexcept {
constexpr bool operator==(variant2 const &other) const noexcept requires (std::equality_comparable<T> && std::equality_comparable<U>) {
if (discriminant_ != other.discriminant_) {
return false;
}
Expand All @@ -742,7 +743,7 @@ namespace dice::template_library {
}
}

constexpr auto operator<=>(variant2 const &other) const noexcept {
constexpr auto operator<=>(variant2 const &other) const noexcept requires (std::three_way_comparable<T> && std::three_way_comparable<U>) {
using ret_type = std::common_comparison_category_t<std::compare_three_way_result_t<T>, std::compare_three_way_result_t<U>>;

if (discriminant_ != other.discriminant_) {
Expand Down Expand Up @@ -903,4 +904,23 @@ namespace dice::template_library {

} // namespace dice::template_library

template<typename T, typename U> requires (std::formattable<T, char> && std::formattable<U, char>)
struct std::formatter<::dice::template_library::variant2<T, U>> {
template<typename Ctx>
constexpr auto parse(Ctx &ctx) {
return ctx.begin();
}

template<typename Ctx>
auto format(::dice::template_library::variant2<T, U> const &var, Ctx &ctx) const {
// formatting the same way libfmt does
if (var.valueless_by_exception()) {
return std::format_to(ctx.out(), "variant(valueless by exception)");
}
return ::dice::template_library::visit([&ctx](auto const &value) {
return std::format_to(ctx.out(), "variant({})", value);
}, var);
}
};

#endif // DICE_TEMPLATELIBRARY_VARIANT2_HPP
17 changes: 17 additions & 0 deletions tests/tests_type_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ TEST_SUITE("type_list") {
static_assert(std::is_same_v<tl::filter_t<t1, pred>, tl::type_list<int const, char const>>);
}

TEST_CASE("flatten") {
static_assert(std::is_same_v<tl::flatten_t<empty_t>, empty_t>);
static_assert(std::is_same_v<tl::flatten_t<tl::type_list<empty_t>>, empty_t>);
static_assert(std::is_same_v<tl::flatten_t<tl::type_list<tl::type_list<int, double>, empty_t, tl::type_list<char, float>>>, tl::type_list<int, double, char, float>>);
static_assert(std::is_same_v<tl::flatten_t<tl::type_list<tl::type_list<tl::type_list<int, double>>>>, tl::type_list<tl::type_list<int, double>>>);
}

TEST_CASE("generate") {
static_assert(std::is_same_v<tl::generate_t<0, [] { }>, empty_t>);

Expand Down Expand Up @@ -302,6 +309,16 @@ TEST_SUITE("type_list") {
static_assert(std::is_same_v<tl::integer_sequence_to_type_list_t<iseq>, expected_iseq_tl>);
}

TEST_CASE("tuple_to_type_list") {
using empty_tuple = std::tuple<>;
using pair = std::pair<int, double>;
using tuple = std::tuple<char, float, double>;

static_assert(std::is_same_v<tl::tuple_to_type_list_t<empty_tuple>, empty_t>);
static_assert(std::is_same_v<tl::tuple_to_type_list_t<tuple>, tl::type_list<char, float, double>>);
static_assert(std::is_same_v<tl::tuple_to_type_list_t<pair>, tl::type_list<int, double>>);
}

TEST_CASE("for_each") {
using t1 = tl::type_list<int32_t, int64_t, int16_t>;

Expand Down
81 changes: 53 additions & 28 deletions tests/tests_variant2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,47 @@

using namespace std::string_literals;

struct make_valueless {
make_valueless() {
throw std::runtime_error{"aaa"};
}

explicit make_valueless(std::nothrow_t) noexcept {}

make_valueless(make_valueless const &) {
throw std::runtime_error{"aaa"};
}

make_valueless(make_valueless &&) {
throw std::runtime_error{"aaa"};
}

make_valueless &operator=(make_valueless const &) {
throw std::runtime_error{"aaa"};
}

make_valueless &operator=(make_valueless &&) {
throw std::runtime_error{"aaa"};
}

~make_valueless() noexcept = default;

auto operator<=>(make_valueless const &) const noexcept = default;
};

template<>
struct std::formatter<make_valueless> {
template<typename Ctx>
constexpr auto parse(Ctx &parse_ctx) {
return parse_ctx.begin();
}

template<typename Ctx>
auto format(make_valueless const &, Ctx &format_ctx) const {
return std::format_to(format_ctx.out(), "make_valueluess");
}
};

TEST_SUITE("variant2") {
using namespace dice::template_library;

Expand All @@ -29,34 +70,6 @@ TEST_SUITE("variant2") {
&& std::is_const_v<std::remove_reference_t<T>> == std::is_const_v<std::remove_reference_t<U>>;


struct make_valueless {
make_valueless() {
throw std::runtime_error{"aaa"};
}

explicit make_valueless(std::nothrow_t) noexcept {}

make_valueless(make_valueless const &) {
throw std::runtime_error{"aaa"};
}

make_valueless(make_valueless &&) {
throw std::runtime_error{"aaa"};
}

make_valueless &operator=(make_valueless const &) {
throw std::runtime_error{"aaa"};
}

make_valueless &operator=(make_valueless &&) {
throw std::runtime_error{"aaa"};
}

~make_valueless() noexcept = default;

auto operator<=>(make_valueless const &) const noexcept = default;
};

template<typename T, typename Variant>
void check_acessors(Variant &&x, T const &expected_val) {
static constexpr size_t index = variant_index<T, std::remove_cvref_t<Variant>>::value;
Expand Down Expand Up @@ -289,4 +302,16 @@ TEST_SUITE("variant2") {
static_assert(!std::is_trivially_destructible_v<var2>);
static_assert(!std::is_trivially_copyable_v<var2>);
}

TEST_CASE("formatting") {
CHECK(std::format("{}", variant2<int, double>{42}) == "variant(42)");
CHECK(std::format("{}", variant2<int, double>{1.5}) == "variant(1.5)");

variant2<int, make_valueless> valueless{};
try {
Comment thread
nkaralis marked this conversation as resolved.
valueless = make_valueless{std::nothrow};
} catch (...) {
}
CHECK(std::format("{}", valueless) == "variant(valueless by exception)");
}
}
Loading