Skip to content

Commit

Permalink
tuple19: add join and fmt support
Browse files Browse the repository at this point in the history
  • Loading branch information
arBmind committed Oct 26, 2023
1 parent 036292c commit 1079bff
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 2 deletions.
36 changes: 36 additions & 0 deletions src/tuple19.lib/tuple19/Tuple.fmt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once
#include "Tuple.h"

/// note: for this header you need fmt library (not included as library dependency)
#include <fmt/format.h>

namespace tuple19 {

/// use values of the tuple as format arguments
/// note: you still have to craft the proper format string!
/// usage: vformat(formatStr, tuple19::make_format_args(argsTuple));
template<class... Ts> constexpr auto make_format_args(Tuple<Ts...> const& args) {
return [&]<size_t... Is>(std::index_sequence<Is...> const&) {
return fmt::make_format_args(args.template at<Is>()...);
}
(std::make_index_sequence<sizeof...(Ts)>{});
}

} // namespace tuple19

template<class... Ts, class Char> struct fmt::formatter<tuple19::Tuple<Ts...>, Char> {
constexpr auto parse(fmt::basic_format_parse_context<Char>& ctx) { return ctx.begin(); }

template<typename FormatContext> auto format(tuple19::Tuple<Ts...> const& v, FormatContext& ctx) {
if constexpr (sizeof...(Ts) == 0) {
return fmt::format_to(ctx.out(), "Tuple<>");
}
else {
[&]<size_t... Is>(std::index_sequence<0, Is...> const&) {
fmt::format_to(ctx.out(), "{}", v.template at<0>());
(fmt::format_to(ctx.out(), ", {}", v.template at<Is>()), ...);
}
(std::make_index_sequence<sizeof...(Ts)>{});
}
}
};
6 changes: 4 additions & 2 deletions src/tuple19.lib/tuple19/Tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "meta19/Type.h"

#include <stddef.h> // size_t
#include <type_traits>
#include <type_traits> // index_sequence
#include <utility>

namespace tuple19 {
Expand Down Expand Up @@ -35,7 +35,7 @@ template<class T, size_t I> constexpr auto indexOf(TupleEntry<I, T>*) -> size_t

template<class... Ts> struct Tuple {
private:
template<class Is> struct IndexedTuple;
template<class> struct IndexedTuple;

template<size_t... Is> struct IndexedTuple<std::index_sequence<Is...>> : details::TupleEntry<Is, Ts>... {

Expand Down Expand Up @@ -69,6 +69,8 @@ template<class... Ts> struct Tuple {

bool operator==(const Tuple&) const = default;

/// set all values given with arguments (the rest keeps default initialisation)
/// note: works best if types in tuple are unique
template<class... Os> static constexpr auto fromArgs(Os&&... os) -> Tuple {
auto res = Tuple{};
((res.amendOf(type<StoredOf<Os>>) = std::forward<Os>(os)), ...);
Expand Down
29 changes: 29 additions & 0 deletions src/tuple19.lib/tuple19/Tuple.join.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once
#include "Tuple.h"

namespace tuple19 {

/// returns a tuple with all values of a and b
/// note: types don't have to be uniqe
template<class... As, class... Bs>
auto joinTuples(Tuple<As...> const& a, Tuple<Bs...> const& b) -> Tuple<As..., Bs...> {
return [&]<std::size_t... AIs, size_t... BIs>(
std::index_sequence<AIs...> const&,
std::index_sequence<BIs...> const&)
->Tuple<As..., Bs...> {
return {a.template at<AIs>()..., b.template at<BIs>()...};
}
(std::make_index_sequence<sizeof...(As)>{}, std::make_index_sequence<sizeof...(Bs)>{});
}

template<class... As, class... Bs> auto joinTuples(Tuple<As...>&& a, Tuple<Bs...>&& b) -> Tuple<As..., Bs...> {
return [&]<std::size_t... AIs, size_t... BIs>(
std::index_sequence<AIs...> const&,
std::index_sequence<BIs...> const&)
->Tuple<As..., Bs...> {
return {std::move(a.template amendAt<AIs>())..., std::move(b.template amendAt<BIs>())...};
}
(std::make_index_sequence<sizeof...(As)>{}, std::make_index_sequence<sizeof...(Bs)>{});
}

} // namespace tuple19
30 changes: 30 additions & 0 deletions src/tuple19.lib/tuple19/Tuple.join.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "Tuple.h"

#include "Tuple.join.h"
#include "Tuple.ostream.h"

#include <gtest/gtest.h>
#include <string>

using namespace tuple19;

TEST(TupleJoin, constants) {
using meta19::_index;
using meta19::type;

using A = Tuple<char, int, double>;
auto a = A{'x', 23, 4.2};

using B = Tuple<std::string, float, int>;
auto b = B{"!", 4.2f, 42};

using C = Tuple<char, int, double, std::string, float, int>;
auto c = C{'x', 23, 4.2, "!", 4.2f, 42};

EXPECT_EQ(joinTuples(a, b), c);
}

TEST(TupleJoin, move) {
//
EXPECT_EQ(joinTuples(Tuple{'a', 12}, Tuple{4.2, 4.2f, 23}), (Tuple{'a', 12, 4.2, 4.2f, 23}));
}
2 changes: 2 additions & 0 deletions src/tuple19.lib/tuple19/tuple19.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ Product {

files: [
"Tuple.bind.h",
"Tuple.fmt.h",
"Tuple.h",
"Tuple.join.h",
"Tuple.ostream.h",
"Tuple.trait.h",
]
Expand Down
1 change: 1 addition & 0 deletions src/tuple19.lib/tuple19/tuple19.tests.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Application {

files: [
"Tuple.bind.test.cpp",
"Tuple.join.test.cpp",
"Tuple.test.cpp",
]
}

0 comments on commit 1079bff

Please sign in to comment.