mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
Tested on a C++17 compatible compiler, fixed a bunch of issues and made all the tests compil and run successfully
This commit is contained in:
36
README.md
36
README.md
@@ -15,8 +15,9 @@ Develop: | [](https://travis-ci.org/apolukhin/magic_get) <!-- [](https://ci.appveyor.com/project/apolukhin/boost-dll/branch/master) --> | [](https://coveralls.io/github/apolukhin/magic_get?branch=master) | <!-- [details...](http://www.boost.org/development/tests/master/developer/pfr.html)) -->
|
||||
|
||||
|
||||
### Motivating example
|
||||
### C++14 Motivating Example
|
||||
```c++
|
||||
// requires: C++14
|
||||
#include <iostream>
|
||||
#include "boost/pfr.hpp"
|
||||
|
||||
@@ -41,15 +42,46 @@ Outputs:
|
||||
my_struct has 3 fields: {100, H, 3.14159}
|
||||
```
|
||||
|
||||
### C++17 Motivating Example
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include "boost/pfr.hpp"
|
||||
|
||||
struct my_struct { // no ostream operator defined!
|
||||
std::string s;
|
||||
int i;
|
||||
};
|
||||
|
||||
int main() {
|
||||
using namespace boost::pfr::ops; // C++17 out-of-the-box ostream operators for aggregate initializables!
|
||||
|
||||
my_struct s{{"Das ist fantastisch!"}, 100};
|
||||
std::cout << "my_struct has " << boost::pfr::tuple_size<my_struct>::value
|
||||
<< " fields: " << s << "\n";
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Outputs:
|
||||
```
|
||||
my_struct has 2 fields: {"Das ist fantastisch!", 100}
|
||||
```
|
||||
|
||||
|
||||
### Requirements and Limitations
|
||||
|
||||
General:
|
||||
* C++14 compatible compiler (GCC-5.0+, Clang, ...)
|
||||
* Static variables are ignored
|
||||
|
||||
C++14 limitations (C++17 fixes those):
|
||||
C++14 limitations:
|
||||
* T must be constexpr aggregate initializable and must not contain references nor bitfields
|
||||
|
||||
C++17 limitations:
|
||||
* T must be aggregate initializable and must not contain arrays (but may contain `std::array` like classes)
|
||||
|
||||
|
||||
### License
|
||||
|
||||
Distributed under the [Boost Software License, Version 1.0](http://boost.org/LICENSE_1_0.txt).
|
||||
|
||||
@@ -624,6 +624,9 @@ struct ubiq_constructor_constexpr_copy {
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
|
||||
#if !BOOST_PFR_USE_CPP17
|
||||
|
||||
template <class T, std::size_t... I>
|
||||
struct is_constexpr_aggregate_initializable { // TODO: try to fix it
|
||||
template <T = T{ ubiq_constructor_constexpr_copy{I}... } >
|
||||
@@ -712,6 +715,7 @@ void for_each_field_dispatcher(T&& t, F&& f, std::index_sequence<I...>) {
|
||||
);
|
||||
}
|
||||
|
||||
#endif // #if !BOOST_PFR_USE_CPP17
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -16,10 +16,8 @@ namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_dispatcher(T&& t, F&& f, std::index_sequence<I...>) {
|
||||
::boost::pfr::detail::for_each_field_impl(
|
||||
detail::as_tuple(std::forward<T>(t)),
|
||||
std::forward<F>(f),
|
||||
std::index_sequence<I...>{}
|
||||
std::forward<F>(f)(
|
||||
detail::as_tuple(std::forward<T>(t))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,16 +11,46 @@
|
||||
|
||||
#include <boost/pfr/detail/sequence_tuple.hpp>
|
||||
#include <iosfwd> // stream operators
|
||||
#include <iomanip>
|
||||
|
||||
// Forward declaration
|
||||
namespace std {
|
||||
template <class CharT, class Traits> class basic_string_view;
|
||||
}
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
|
||||
inline auto quoted_helper(const std::string& s) noexcept {
|
||||
return std::quoted(s);
|
||||
}
|
||||
|
||||
template <class CharT, class Traits>
|
||||
inline auto quoted_helper(const std::basic_string_view<CharT, Traits>& s) noexcept {
|
||||
return std::quoted(s);
|
||||
}
|
||||
|
||||
inline auto quoted_helper(std::string& s) noexcept {
|
||||
return std::quoted(s);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline decltype(auto) quoted_helper(T&& v) noexcept {
|
||||
return std::forward<T>(v);
|
||||
}
|
||||
|
||||
template <std::size_t I, std::size_t N>
|
||||
struct print_impl {
|
||||
template <class Stream, class T>
|
||||
static void print (Stream& out, const T& value) {
|
||||
if (!!I) out << ", ";
|
||||
out << boost::pfr::detail::sequence_tuple::get<I>(value);
|
||||
out << quoted_helper(boost::pfr::detail::sequence_tuple::get<I>(value));
|
||||
print_impl<I + 1, N>::print(out, value);
|
||||
}
|
||||
|
||||
template <class Stream, class T>
|
||||
static void print (Stream& out, const std::string& value) {
|
||||
if (!!I) out << ", ";
|
||||
out << std::quoted( boost::pfr::detail::sequence_tuple::get<I>(value) );
|
||||
print_impl<I + 1, N>::print(out, value);
|
||||
}
|
||||
};
|
||||
@@ -42,7 +72,7 @@ struct read_impl {
|
||||
in >> ignore;
|
||||
if (ignore != ' ') in.setstate(Stream::failbit);
|
||||
}
|
||||
in >> boost::pfr::detail::sequence_tuple::get<I>(value);
|
||||
in >> quoted_helper( boost::pfr::detail::sequence_tuple::get<I>(value) );
|
||||
read_impl<I + 1, N>::read(in, value);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (c) 2016 Antony Polukhin
|
||||
# Copyright (c) 2016-2017 Antony Polukhin
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -10,8 +10,8 @@
|
||||
import sys
|
||||
import string
|
||||
|
||||
# Skipping some letters that mey produce keywords or are hard to read
|
||||
ascii_letters = string.ascii_letters.replace("o", "").replace("O", "").replace("i", "").replace("I", "")
|
||||
# Skipping some letters that may produce keywords or are hard to read, or shadow template parameters
|
||||
ascii_letters = string.ascii_letters.replace("o", "").replace("O", "").replace("i", "").replace("I", "").replace("T", "")
|
||||
|
||||
PROLOGUE = """// Copyright (c) 2016-2017 Antony Polukhin
|
||||
//
|
||||
@@ -29,7 +29,7 @@ PROLOGUE = """// Copyright (c) 2016-2017 Antony Polukhin
|
||||
|
||||
#include <boost/pfr/detail/config.hpp>
|
||||
|
||||
#if BOOST_PFR_USE_CPP17
|
||||
#if !BOOST_PFR_USE_CPP17
|
||||
# error C++17 is required for this header.
|
||||
#endif
|
||||
|
||||
@@ -48,6 +48,18 @@ constexpr auto as_tuple_impl(T&& /*val*/, size_t_<0>) noexcept {
|
||||
return sequence_tuple::tuple<>{};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr auto as_tuple_impl(T&& val, size_t_<1>, std::enable_if_t<std::is_class< std::remove_cv_t<std::remove_reference_t<T>> >::value>* = 0) noexcept {
|
||||
auto& [a] = std::forward<T>(val);
|
||||
return ::boost::pfr::detail::make_tuple_of_references(a);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
constexpr auto as_tuple_impl(T&& val, size_t_<1>, std::enable_if_t<!std::is_class< std::remove_cv_t<std::remove_reference_t<T>> >::value>* = 0) noexcept {
|
||||
return ::boost::pfr::detail::make_tuple_of_references( std::forward<T>(val) );
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
############################################################################################################################
|
||||
@@ -57,13 +69,13 @@ EPILOGUE = """
|
||||
template <class T>
|
||||
constexpr auto as_tuple(const T& val) noexcept {
|
||||
typedef size_t_<fields_count<T>()> fields_count_tag;
|
||||
return detail::as_tuple_impl(val, fields_count_tag{});
|
||||
return boost::pfr::detail::as_tuple_impl(val, fields_count_tag{});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr auto as_tuple(T& val) noexcept {
|
||||
typedef size_t_<fields_count<T>()> fields_count_tag;
|
||||
return detail::as_tuple_impl(val, fields_count_tag{});
|
||||
return boost::pfr::detail::as_tuple_impl(val, fields_count_tag{});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -75,15 +87,24 @@ using as_tuple_t = decltype( ::boost::pfr::detail::as_tuple(std::declval<T&>())
|
||||
"""
|
||||
|
||||
############################################################################################################################
|
||||
generate_sfinae_attempts = False
|
||||
|
||||
indexes = ""
|
||||
|
||||
if generate_sfinae_attempts:
|
||||
print """
|
||||
template <class T, std::size_t I>
|
||||
constexpr auto as_tuple_impl(T&& val, size_t_<I>) noexcept {
|
||||
return as_tuple_impl( std::forward<T>(val), size_t_<I - 1>{});
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
indexes = " a"
|
||||
print PROLOGUE
|
||||
funcs_count = 100 if len(sys.argv) == 1 else int(sys.argv[1])
|
||||
max_args_on_a_line = len(ascii_letters)
|
||||
for i in xrange(funcs_count):
|
||||
if i == 0:
|
||||
indexes = " "
|
||||
elif i % max_args_on_a_line == 0:
|
||||
for i in xrange(1, funcs_count):
|
||||
if i % max_args_on_a_line == 0:
|
||||
indexes += ",\n "
|
||||
else:
|
||||
indexes += ","
|
||||
@@ -108,4 +129,10 @@ for i in xrange(funcs_count):
|
||||
|
||||
print "}\n"
|
||||
|
||||
if generate_sfinae_attempts:
|
||||
print "template <class T>"
|
||||
print "constexpr auto as_tuple_impl(T&& val, size_t_<" + str(i + 1) + "> v) noexcept"
|
||||
print " ->decltype( ::boost::pfr::detail::as_tuple_impl0(std::forward<T>(val), v) )"
|
||||
print "{ return ::boost::pfr::detail::as_tuple_impl0(std::forward<T>(val), v); }\n"
|
||||
|
||||
print EPILOGUE
|
||||
|
||||
@@ -34,15 +34,15 @@ struct adl_hash {
|
||||
};
|
||||
|
||||
struct comparable_struct {
|
||||
int i; short s; char data[50]; bool bl; int a,b,c,d,e,f;
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
|
||||
BOOST_PFR_TEST_FUNCTIONS_FOR(comparable_struct)
|
||||
|
||||
void test_comparable_struct() {
|
||||
comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11};
|
||||
comparable_struct s1 {0, 1, false, 6,7,8,9,10,11};
|
||||
comparable_struct s2 = s1;
|
||||
comparable_struct s3 {0, 1, "Hello", false, 6,7,8,9,10,11111};
|
||||
comparable_struct s3 {0, 1, false, 6,7,8,9,10,11111};
|
||||
BOOST_TEST_EQ(s1, s2);
|
||||
BOOST_TEST(s1 <= s2);
|
||||
BOOST_TEST(s1 >= s2);
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
template <class T>
|
||||
void test_comparable_struct() {
|
||||
T s1 {0, 1, "Hello", false, 6,7,8,9,10,11};
|
||||
T s1 {0, 1, false, 6,7,8,9,10,11};
|
||||
T s2 = s1;
|
||||
T s3 {0, 1, "Hello", false, 6,7,8,9,10,11111};
|
||||
T s3 {0, 1, false, 6,7,8,9,10,11111};
|
||||
BOOST_TEST(s1 == s2);
|
||||
BOOST_TEST(s1 <= s2);
|
||||
BOOST_TEST(s1 >= s2);
|
||||
@@ -90,7 +90,7 @@ void test_with_contatiners() {
|
||||
|
||||
namespace foo {
|
||||
struct comparable_struct {
|
||||
int i; short s; char data[50]; bool bl; int a,b,c,d,e,f;
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ int main() {
|
||||
test_comparable_struct<foo::comparable_struct>();
|
||||
|
||||
struct local_comparable_struct {
|
||||
int i; short s; char data[50]; bool bl; int a,b,c,d,e,f;
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
|
||||
test_comparable_struct<local_comparable_struct>();
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
template <class T>
|
||||
void test_comparable_struct() {
|
||||
using namespace BOOST_PFR_TEST_NAMESPECE;
|
||||
T s1 {0, 1, "Hello", false, 6,7,8,9,10,11};
|
||||
T s1 {0, 1, false, 6,7,8,9,10,11};
|
||||
T s2 = s1;
|
||||
T s3 {0, 1, "Hello", false, 6,7,8,9,10,11111};
|
||||
T s3 {0, 1, false, 6,7,8,9,10,11111};
|
||||
BOOST_TEST(s1 == s2);
|
||||
BOOST_TEST(s1 <= s2);
|
||||
BOOST_TEST(s1 >= s2);
|
||||
@@ -71,7 +71,7 @@ void test_implicit_conversions() {
|
||||
|
||||
namespace foo {
|
||||
struct comparable_struct {
|
||||
int i; short s; char data[50]; bool bl; int a,b,c,d,e,f;
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ int main() {
|
||||
test_comparable_struct<foo::comparable_struct>();
|
||||
|
||||
struct local_comparable_struct {
|
||||
int i; short s; char data[50]; bool bl; int a,b,c,d,e,f;
|
||||
int i; short s; bool bl; int a,b,c,d,e,f;
|
||||
};
|
||||
|
||||
test_comparable_struct<local_comparable_struct>();
|
||||
|
||||
@@ -124,7 +124,27 @@ int main() {
|
||||
int f3;
|
||||
std::string f4;
|
||||
};
|
||||
test_type(test4{1, "my o my", '3', 4, "hello there!"});
|
||||
test_type(
|
||||
test4{1, {"my o my"}, '3', 4, {"hello there!"} },
|
||||
"{1, \"my o my\", 3, 4, \"hello there!\"}"
|
||||
);
|
||||
|
||||
#if 0
|
||||
// TODO:
|
||||
std::string f1_referenced{"my O my"};
|
||||
std::string f4_referenced{"Hello There!"};
|
||||
struct test5 {
|
||||
int f0;
|
||||
const std::string& f1;
|
||||
char f2;
|
||||
int f3;
|
||||
const std::string& f4;
|
||||
};
|
||||
to_string_test(
|
||||
test5{1, f1_referenced, '3', 4, f4_referenced },
|
||||
"{1, \"my o my\", 3, 4, \"hello there!\"}"
|
||||
);
|
||||
#endif
|
||||
#endif
|
||||
#endif // BOOST_PFR_TEST_PRECISE
|
||||
|
||||
|
||||
@@ -57,12 +57,24 @@ struct simple {
|
||||
|
||||
|
||||
int main () {
|
||||
int array[100] = {};
|
||||
std::size_t control = 0;
|
||||
boost::pfr::for_each_field(array, [&control](auto&& /*val*/, std::size_t i) {
|
||||
|
||||
int v = {};
|
||||
boost::pfr::for_each_field(v, [&control](auto&& val, std::size_t i) {
|
||||
BOOST_TEST_EQ(i, control);
|
||||
(void)val;
|
||||
++ control;
|
||||
});
|
||||
BOOST_TEST_EQ(control, 1);
|
||||
|
||||
control = 0;
|
||||
int array[100] = {};
|
||||
boost::pfr::for_each_field(array, [&control](auto&& val, std::size_t i) {
|
||||
BOOST_TEST_EQ(i, control);
|
||||
(void)val;
|
||||
++ control;
|
||||
});
|
||||
BOOST_TEST_EQ(control, 100);
|
||||
|
||||
std::stringstream ss;
|
||||
boost::pfr::for_each_field(reg{42, 'a', {}, nullptr, color::green, "hello world!"}, [&ss](auto&& val, std::size_t i) {
|
||||
|
||||
Reference in New Issue
Block a user