From f0a92f01e72630517e9415d99eb068ba9cab907e Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 11 Apr 2016 20:41:37 +0300 Subject: [PATCH] support for empty structures in flat_* methods, slightly more compact streaming operators --- README.md | 6 +++--- magic_get.hpp | 41 +++++++++++++++++++++++++++++++---------- main.cpp | 10 ++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 708697a..5564f83 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ auto flat_tie(T& val, typename std::enable_if< std::is_trivially_assignable void flat_write(std::basic_ostream& out, const T& value); @@ -134,7 +134,7 @@ void flat_write(std::basic_ostream& out, const T& value); /// struct my_struct { int i, short s; }; /// my_struct s; /// std::stringstream ss; -/// ss << "{ 12, 13 }"; +/// ss << "{12, 13}"; /// ss >> s; /// assert(s.i == 12); /// assert(s.i == 13); @@ -152,7 +152,7 @@ void flat_read(std::basic_istream& in, T& value); /// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11}; /// comparable_struct s2 {0, 1, "Hello", false, 6,7,8,9,10,11111}; /// assert(s1 < s2); -/// std::cout << s1 << std::endl; // Outputs: { 0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11 } +/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11} namespace pod_ops; ``` diff --git a/magic_get.hpp b/magic_get.hpp index 398ba95..8894474 100644 --- a/magic_get.hpp +++ b/magic_get.hpp @@ -164,6 +164,18 @@ struct size_array { // libc++ misses constexpr on operat } }; +template <> +struct size_array<0> { // libc++ misses constexpr on operator[] + typedef std::size_t type; + std::size_t data[1]; + + static constexpr std::size_t size() noexcept { return 0; } + + constexpr std::size_t count_nonzeros() const noexcept { + return 0; + } +}; + template constexpr std::size_t get(const size_array& a) noexcept { static_assert(I < N, "Array index out of bounds"); @@ -171,7 +183,8 @@ constexpr std::size_t get(const size_array& a) noexcept { } -template constexpr size_array fields_count_and_type_ids_with_zeros() noexcept; +template constexpr size_array fields_count_and_type_ids_with_zeros(std::enable_if_t::value>* = 0) noexcept; +template constexpr size_array<0> fields_count_and_type_ids_with_zeros(std::enable_if_t::value>* = 0) noexcept; ///////////////////// All the stuff for representing Type as integer and converting integer back to type namespace typeid_conversions { @@ -522,12 +535,17 @@ constexpr void detect_fields_count_and_type_ids(std::size_t*, std::index_sequenc ///////////////////// Returns array of typeids and zeros template -constexpr size_array fields_count_and_type_ids_with_zeros() noexcept { +constexpr size_array fields_count_and_type_ids_with_zeros(std::enable_if_t::value>*) noexcept { size_array types{}; detect_fields_count_and_type_ids(types.data, std::make_index_sequence{}); return types; } +template +constexpr size_array<0> fields_count_and_type_ids_with_zeros(std::enable_if_t::value>*) noexcept { + return size_array<0>{0}; +} + ///////////////////// Returns array of typeids without zeros template constexpr auto array_of_type_ids() noexcept { @@ -556,6 +574,11 @@ constexpr auto as_tuple_impl(std::index_sequence) noexcept { >{}; } +template +constexpr tuple<> as_tuple_impl(std::index_sequence<>) noexcept { + return tuple<>{}; +} + template constexpr auto as_tuple() noexcept { typedef typename std::remove_cv::type type; @@ -727,12 +750,12 @@ namespace detail { /// Example usage: /// struct my_struct { int i, short s; }; /// my_struct s{12, 13}; -/// flat_write(std::cout, s); // outputs '{ 12, 13 }' +/// flat_write(std::cout, s); // outputs '{12, 13}' template void flat_write(std::basic_ostream& out, const T& value) { - out << "{ "; + out << '{'; detail::flat_print_impl<0, flat_tuple_size_v >::print(out, value); - out << " }"; + out << '}'; } @@ -745,9 +768,9 @@ namespace detail { if (!!I) { in >> ignore; if (ignore != ',') in.setstate(Stream::failbit); + in >> ignore; + if (ignore != ' ') in.setstate(Stream::failbit); } - in >> ignore; - if (ignore != ' ') in.setstate(Stream::failbit); in >> flat_get(value); flat_read_impl::read(in, value); } @@ -779,8 +802,6 @@ void flat_read(std::basic_istream& in, T& value) { if (parenthis != '{') in.setstate(std::basic_istream::failbit); detail::flat_read_impl<0, flat_tuple_size_v >::read(in, value); - in >> parenthis; - if (parenthis != ' ') in.setstate(std::basic_istream::failbit); in >> parenthis; if (parenthis != '}') in.setstate(std::basic_istream::failbit); @@ -792,7 +813,7 @@ void flat_read(std::basic_istream& in, T& value) { namespace detail { template using same_pods_enable = typename std::enable_if< - std::is_same::value && std::is_pod::value && std::is_pod::value, + std::is_same::value && std::is_pod::value && std::is_class::value, bool >::type; diff --git a/main.cpp b/main.cpp index 11f94ec..1195759 100644 --- a/main.cpp +++ b/main.cpp @@ -225,6 +225,15 @@ void test_comparable_struct() { assert(i != j); } +void test_empty_struct() { + struct empty {}; + using namespace pod_ops; + + std::cout << empty{} << std::endl; + + assert(empty{} == empty{}); +} + int main() { test_compiletime(); test_compiletime_array(); @@ -251,6 +260,7 @@ int main() { test_with_enums(); test_comparable_struct(); + test_empty_struct(); test_print(); }