Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve field count typical case performance #120

Merged
merged 38 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6312e37
Improve field count typical case performance
runer112 Jan 18, 2023
aac7c36
Update performance evaluation
runer112 Jan 23, 2023
57bbe0c
Don't test in parallel
runer112 Jan 24, 2023
096445f
Add complete type precondition and condition evaluation on preconditions
runer112 Jan 24, 2023
de5d6f4
Restore parallel testing
runer112 Jan 24, 2023
28bd7f5
Test `fields_count` with incomplete types
runer112 Jan 24, 2023
e80f7aa
Add more field count tests
runer112 Feb 10, 2023
ca3ca70
Oops
runer112 Feb 10, 2023
dd1ae1c
Prevent unbounded field count test growth
runer112 Feb 11, 2023
ea57b67
Merge branch 'develop' into opt-field-count
runer112 Sep 5, 2024
5b2b1cc
Update copyright years
runer112 Sep 5, 2024
170338c
Address violation of Boost min/max guidelines
runer112 Sep 13, 2024
63374ef
Address unacceptable character '+' in file name
runer112 Sep 13, 2024
a6d0c5f
Prevent unnecessary triggering of last-resort assertion
runer112 Sep 20, 2024
27a5c6e
Address MSVC issue
runer112 Sep 20, 2024
465ff1b
Correct wording: constructible -> initializable
runer112 Sep 20, 2024
5546762
Skip inheritance check for non-classes
runer112 Sep 20, 2024
5e655d4
Skip hand-made aggregate check for non-classes
runer112 Sep 20, 2024
cbc57cc
Test field count for huge types
runer112 Sep 20, 2024
85d05cf
Update overlooked references to renamed internal symbol
runer112 Sep 30, 2024
82770f5
Fix incorrect include path
runer112 Sep 30, 2024
c5424df
Restore empty class aggregate classification
runer112 Sep 30, 2024
ee3238e
Pack huge structs to stay under max size
runer112 Oct 4, 2024
ff14705
Prevent ADL throughout fields_count.hpp
runer112 Oct 4, 2024
d222d98
Restore "is_aggregate_initializable_n" name
runer112 Oct 4, 2024
ae8ce8d
Avoid including <algorithm>
runer112 Oct 4, 2024
f461689
Refine compiler size limits
runer112 Oct 4, 2024
5978e52
Test field count for a type with 1k fields
runer112 Oct 4, 2024
68e6aba
Stop at expected compiler limitation values during exponential search
runer112 Oct 4, 2024
13f29c6
Revert "Prevent unnecessary triggering of last-resort assertion"
runer112 Oct 4, 2024
ab3621c
Revert "Add complete type precondition and condition evaluation on pr…
runer112 Oct 4, 2024
d6677de
Add back complete type precondition
runer112 Oct 4, 2024
cdec333
Restore original whitespace
runer112 Oct 4, 2024
15e42ea
Attempt to match code style
runer112 Oct 4, 2024
d643b5c
Consolidate incomplete struct type test setup
runer112 Oct 4, 2024
4adba12
Prevent ADL
runer112 Oct 4, 2024
8395a30
Match code style
runer112 Oct 7, 2024
fe6f150
Address violation of Boost min/max guidelines
runer112 Oct 7, 2024
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
229 changes: 166 additions & 63 deletions include/boost/pfr/detail/fields_count.hpp

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions test/core/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ test-suite pfr_tests
[ run ../../example/sample_printing.cpp : : : : auto_engine_sample_printing ]
[ run ../../example/get.cpp : : : : auto_engine_get ]
[ run ../../example/quick_examples.cpp : : : : auto_engine_quick ]

[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON=void : fields_count_on_incomplete_type_void ]
[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON="void()" : fields_count_on_incomplete_type_function ]
[ compile-fail fields_count_on_incomplete_type.cpp : <define>BOOST_PFR_RUN_TEST_ON="struct Foo" : fields_count_on_incomplete_type_struct ]
;

local BLACKLIST_TESTS_FOR_LOOPHOLE =
Expand Down
15 changes: 15 additions & 0 deletions test/core/compile-fail/constructible_0_or_more_args.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2023-2024 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)

#include <boost/pfr/tuple_size.hpp>

struct A {
template <typename... Args>
explicit A(Args&&...) {}
};

int main() {
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error
}
15 changes: 15 additions & 0 deletions test/core/compile-fail/constructible_1_or_more_args.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) 2023-2024 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)

#include <boost/pfr/tuple_size.hpp>

struct A {
template <typename Arg0, typename... Args>
explicit A(Arg0&&, Args&&...) {}
};

int main() {
(void)boost::pfr::tuple_size<A>::value; // Must be a compile time error
}
10 changes: 10 additions & 0 deletions test/core/fields_count_on_incomplete_type.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) 2023-2024 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)

#include <boost/pfr/detail/fields_count.hpp>

int main() {
return static_cast<int>(boost::pfr::detail::fields_count<BOOST_PFR_RUN_TEST_ON>());
}
85 changes: 75 additions & 10 deletions test/core/run/bitfields_count.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,82 @@

#include <boost/pfr/tuple_size.hpp>

struct bf {
unsigned int i1: 1;
unsigned int i2: 1;
unsigned int i3: 1;
unsigned int i4: 1;
unsigned int i5: 1;
unsigned int i6: 1;
#include <cstdint>

struct bf7 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
};
static_assert(sizeof(bf7) == 1, "");

int main() {
static_assert(boost::pfr::tuple_size<bf>::value == 6, "");
}
struct bf8 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
};
static_assert(sizeof(bf8) == 1, "");

struct bf16 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t b8 : 1;
uint8_t b9 : 1;
uint8_t b10 : 1;
uint8_t b11 : 1;
uint8_t b12 : 1;
uint8_t b13 : 1;
uint8_t b14 : 1;
uint8_t b15 : 1;
};
static_assert(sizeof(bf16) == 2, "");

struct bf24 {
uint8_t b0 : 1;
uint8_t b1 : 1;
uint8_t b2 : 1;
uint8_t b3 : 1;
uint8_t b4 : 1;
uint8_t b5 : 1;
uint8_t b6 : 1;
uint8_t b7 : 1;
uint8_t b8 : 1;
uint8_t b9 : 1;
uint8_t b10 : 1;
uint8_t b11 : 1;
uint8_t b12 : 1;
uint8_t b13 : 1;
uint8_t b14 : 1;
uint8_t b15 : 1;
uint8_t b16 : 1;
uint8_t b17 : 1;
uint8_t b18 : 1;
uint8_t b19 : 1;
uint8_t b20 : 1;
uint8_t b21 : 1;
uint8_t b22 : 1;
uint8_t b23 : 1;
};
static_assert(sizeof(bf24) == 3, "");

int main() {
static_assert(boost::pfr::tuple_size_v<bf7> == 7, "");
static_assert(boost::pfr::tuple_size_v<bf8> == 8, "");
static_assert(boost::pfr::tuple_size_v<bf16> == 16, "");
static_assert(boost::pfr::tuple_size_v<bf24> == 24, "");
}
63 changes: 63 additions & 0 deletions test/core/run/huge_count.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) 2024 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)

#include <boost/pfr/tuple_size.hpp>

#include <climits>
#include <cstdint>

#if defined(__clang__)
# if SIZE_MAX > (1ULL << 32) - 1
# define ARRAY_MAX (SIZE_MAX >> 3)
# else
# define ARRAY_MAX SIZE_MAX
# endif
# define OBJECT_MAX SIZE_MAX
#elif defined(__GNUC__)
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX (SIZE_MAX >> 1)
#elif defined(_MSC_VER)
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX UINT_MAX
#else // Let's play it safe
# define ARRAY_MAX INT_MAX
# define OBJECT_MAX INT_MAX
#endif

#pragma pack(1)
struct A {
char x[ARRAY_MAX <= (OBJECT_MAX >> 3) ? ARRAY_MAX : OBJECT_MAX >> 3];
};

struct B {
A a;
A b;
A c;
A d;
A e;
A f;
A g;
A h;
};

struct C {
A& a;
A b;
A c;
A d;
A e;
A f;
A g;
A h;
};
#pragma pack()

int main() {
#ifndef _MSC_VER
static_assert(boost::pfr::tuple_size_v<char[ARRAY_MAX]> == ARRAY_MAX, "");
#endif
static_assert(boost::pfr::tuple_size_v<B> == 8, "");
static_assert(boost::pfr::tuple_size_v<C> == 8, "");
}
Loading
Loading