-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
define printer for ranges, types without stream insertion (#6)
Change-Id: I60bf6c70b610d38da41bc1bd55a9c3f4fac42b2d
- Loading branch information
Showing
11 changed files
with
215 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#pragma once | ||
|
||
#include "src/detail/is_range.hpp" | ||
#include "src/detail/priority.hpp" | ||
#include "src/detail/type_name.hpp" | ||
#include "src/rope.hpp" | ||
|
||
#include <cstddef> | ||
#include <ostream> | ||
#include <tuple> | ||
#include <utility> | ||
|
||
namespace skytest::detail { | ||
template <class R> | ||
struct range_fmt; | ||
template <class... Ts> | ||
struct tuple_fmt; | ||
|
||
class arg_fmt_fn | ||
{ | ||
struct ostream_inserter | ||
{ | ||
template <class T> | ||
auto operator()(const T& value) | ||
-> decltype(std::declval<std::ostream&>() << value); | ||
}; | ||
|
||
template <class T> | ||
static constexpr auto is_ostreamable_v = | ||
std::is_invocable_r_v<std::ostream&, ostream_inserter, const T&>; | ||
|
||
template < | ||
class R, | ||
std::enable_if_t<is_range_v<R> and not is_ostreamable_v<R>, bool> = true> | ||
static constexpr auto impl(priority<3>, const R& arg) | ||
{ | ||
return range_fmt<R>{arg}; | ||
} | ||
|
||
template < | ||
class... Ts, | ||
std::enable_if_t<not is_ostreamable_v<std::tuple<Ts...>>, bool> = true> | ||
static constexpr auto impl(priority<2>, const std::tuple<Ts...>& arg) | ||
{ | ||
return tuple_fmt<Ts...>{arg}; | ||
} | ||
|
||
template <class T, std::enable_if_t<is_ostreamable_v<T>, bool> = true> | ||
static constexpr auto& impl(priority<1>, const T& arg) | ||
{ | ||
return arg; | ||
} | ||
|
||
template <class T> | ||
static constexpr auto impl(priority<0>, const T&) | ||
{ | ||
return rope<2>{type_name<T>, "{...}"}; | ||
} | ||
|
||
public: | ||
template <class T> | ||
constexpr decltype(auto) operator()(const T & arg) const | ||
{ | ||
return impl(priority<3>{}, arg); | ||
} | ||
}; | ||
inline constexpr auto arg_fmt = arg_fmt_fn{}; | ||
|
||
template <class R> | ||
struct range_fmt | ||
{ | ||
const R& range; | ||
|
||
friend auto& operator<<(std::ostream& os, const range_fmt& f) | ||
{ | ||
auto first = true; | ||
|
||
os << "["; | ||
for (const auto& value : f.range) { | ||
os << (std::exchange(first, false) ? "" : ", ") << value; | ||
} | ||
os << "]"; | ||
return os; | ||
} | ||
}; | ||
|
||
template <class... Ts> | ||
struct tuple_fmt | ||
{ | ||
const std::tuple<Ts...>& value; | ||
|
||
template <std::size_t... Is> | ||
auto& stream_insert(std::index_sequence<Is...>, std::ostream& os) const | ||
{ | ||
std::ignore = | ||
((os << (Is == 0 ? "" : ", ") << arg_fmt(std::get<Is>(value)), true) and | ||
...); | ||
return os; | ||
} | ||
|
||
friend auto& operator<<(std::ostream& os, const tuple_fmt& tup) | ||
{ | ||
return tup.stream_insert(std::index_sequence_for<Ts...>{}, os); | ||
} | ||
}; | ||
|
||
} // namespace skytest::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#pragma once | ||
|
||
#include <type_traits> | ||
#include <utility> | ||
|
||
namespace skytest::detail { | ||
|
||
template <class T, class = void> | ||
struct is_range : std::false_type | ||
{}; | ||
template <class T> | ||
struct is_range< | ||
T, | ||
std::enable_if_t< | ||
decltype(std::declval<T&>().begin(), | ||
std::declval<T&>().end(), | ||
std::true_type{})::value>> : std::true_type | ||
{}; | ||
|
||
template <class T> | ||
inline constexpr auto is_range_v = is_range<T>::value; | ||
|
||
} // namespace skytest::detail |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#include "skytest/skytest.hpp" | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <iterator> | ||
#include <ostream> | ||
#include <string_view> | ||
|
||
struct empty_desc | ||
{ | ||
using notation_type = skytest::notation::function; | ||
static constexpr auto symbol = std::string_view{"empty"}; | ||
}; | ||
constexpr auto empty = skytest::pred(empty_desc{}, [](const auto& rng) { | ||
return std::empty(rng); | ||
}); | ||
|
||
template <class T, std::size_t N> | ||
struct array : std::array<T, N> | ||
{ | ||
friend auto& operator<<(std::ostream& os, const array& arr) | ||
{ | ||
for (const auto& x : arr) { | ||
os << "{" << x << "}"; | ||
} | ||
return os; | ||
} | ||
}; | ||
|
||
struct wrapped | ||
{ | ||
int value; | ||
|
||
friend constexpr auto operator==(wrapped, wrapped) { return false; } | ||
}; | ||
|
||
auto main() -> int | ||
{ | ||
using namespace ::skytest::literals; | ||
using ::skytest::eq; | ||
using ::skytest::expect; | ||
|
||
"array uses default range arg fmt"_test = [] { | ||
return expect(empty(std::array{1, 2, 3})); | ||
}; | ||
|
||
"custom array uses custom fmt"_test = [] { | ||
return expect(empty(array<int, 2>{4, 5})); | ||
}; | ||
|
||
"type without operator<< is displayed"_test = [] { | ||
return expect(eq(wrapped{1}, wrapped{2})); | ||
}; | ||
} |
Oops, something went wrong.