2
0
mirror of https://github.com/boostorg/pfr.git synced 2026-01-19 04:22:13 +00:00

Add multiple tests from different bug reports and make sure that ever… (#222)

…ything works with new unsafe_declval and with sturctured binding pack

Fixes: https://github.com/boostorg/pfr/issues/208,  https://github.com/boostorg/pfr/issues/110, https://github.com/boostorg/pfr/issues/126
Closes: https://github.com/boostorg/pfr/pull/212
Relates: https://github.com/boostorg/pfr/issues/173
This commit is contained in:
Antony Polukhin
2025-09-14 14:59:25 +03:00
committed by GitHub
parent fc2dba87d6
commit 4f9e6457b0
8 changed files with 165 additions and 3 deletions

View File

@@ -0,0 +1,37 @@
// Copyright (c) 2025-2025 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)
// Test from https://github.com/boostorg/pfr/issues/126
#include <boost/pfr.hpp>
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(NoCopy&&) = delete;
NoCopy& operator=(NoCopy&&) = delete;
NoCopy& operator=(NoCopy const&) = delete;
};
struct Group {
NoCopy m;
NoCopy m2;
NoCopy m3;
NoCopy m4;
};
Group ReturnGroup() { return {};}
int main()
{
#ifdef __cpp_lib_is_aggregate
static_assert(std::is_aggregate_v<Group>, "Group is totally an aggregate");
#endif
static_assert(BOOST_PFR_HAS_GUARANTEED_COPY_ELISION, "Compiler implements mandatory copy elision");
Group aggregate_init_test{{}, {}, {}, {}};
Group elision_test = ReturnGroup();
return boost::pfr::tuple_size_v<Group>;
}

View File

@@ -20,8 +20,17 @@ void test_get_rvalue() {
std::make_unique<int>(43),
};
// Some _MSC_VER are broken:
// boost/pfr/detail/fields_count.hpp(469): error C2338: static_assert failed:
// '====================> Boost.PFR: If there's no other failed static
// asserts then something went wrong. Please report this issue to the github
// along with the structure you're reflecting.'
//
// No known workaround
#if !defined(_MSC_VER) || _MSC_VER != 1944 || !(BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE)
auto p = boost::pfr::get<0>(std::move(x));
BOOST_TEST_EQ(*p, 42);
#endif
}
int main() {

View File

@@ -9,6 +9,15 @@
#include <boost/pfr.hpp>
#include <boost/core/lightweight_test.hpp>
// Some _MSC_VER are broken:
// boost/pfr/detail/fields_count.hpp(469): error C2338: static_assert failed:
// '====================> Boost.PFR: If there's no other failed static
// asserts then something went wrong. Please report this issue to the github
// along with the structure you're reflecting.'
//
// No known workaround
#if !defined(_MSC_VER) || _MSC_VER != 1944 || !(BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE)
struct Message {
std::unique_ptr<int> data;
};
@@ -35,3 +44,9 @@ int main() {
return boost::report_errors();
}
#else
int main() {
return boost::report_errors();
}
#endif

View File

@@ -7,6 +7,7 @@
#include <boost/pfr/core.hpp>
#include <memory>
#include <string>
#include <type_traits>
@@ -47,6 +48,12 @@ struct other_anon_with_optional {
std::optional<some::struct2> d;
};
// from https://github.com/boostorg/pfr/issues/110
struct optional_linked_list {
int value;
std::optional<std::unique_ptr<optional_linked_list>> next;
};
#endif
struct other_anon {
@@ -93,6 +100,8 @@ void test_in_non_non_ns() {
other_anon_with_optional opt{"test again", {}, {}, {}};
auto opt_val = boost::pfr::structure_tie(opt);
BOOST_TEST_EQ(std::get<0>(opt_val), "test again");
static_assert(boost::pfr::tuple_size_v<optional_linked_list> == 2, "");
#endif
}

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2025-2025 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.hpp>
// Test inspired by https://github.com/boostorg/pfr/issues/208
#include <atomic>
#include <memory>
#include <string>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
template <typename T>
struct Field {
Field() = default;
template<typename Arg, class = decltype(T{std::declval<Arg&&>()})>
constexpr Field(Arg&& arg) : value_{std::forward<Arg>(arg)} {}
private:
[[no_unique_address]] T value_;
};
struct CustomFields2 {
Field<int> some_int;
Field<std::vector<int>> some_vector;
Field<std::unique_ptr<int>> some_unique_ptr;
Field<std::shared_ptr<int>> some_shared_ptr;
Field<std::atomic<int>> some_atomic;
};
int main() {
// Compilers have issues with this test in C++17.
//
// GCC-9 and GCC-10 are fine
//
// GCC-11:
// ./boost/pfr/detail/fields_count.hpp:351:58: in constexpr expansion of boost::pfr::detail::fields_count_binary_search<CustomFields2, 0, 5>((boost::pfr::detail::is_one_element_range<0, 5>{}, boost::pfr::detail::is_one_element_range<0, 5>()), 1)
// libs/pfr/test/core_name/run/unique_ptr_wrapper.cpp:23:32: error: use of deleted function std::atomic<int>::atomic(const std::atomic<int>&)
// 23 | constexpr Field(Arg&& arg) : value_{std::forward<Arg>(arg)} {}
// | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// GCC-12:
// libs/pfr/test/core_name/run/unique_ptr_wrapper.cpp:39:39: required from here
// libs/pfr/test/core_name/run/unique_ptr_wrapper.cpp:23:32: error: use of deleted function std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int]
// 23 | constexpr Field(Arg&& arg) : value_{std::forward<Arg>(arg)} {}
// | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// GCC-14 is fine
//
// Because of the above issues we test mostly in C++26.
#if BOOST_PFR_USE_CPP26 || (defined(__GNUC__) && (__GNUC__ != 11 && __GNUC__ != 12)) || defined(__clang__)
CustomFields2 cf2;
boost::pfr::for_each_field_with_name(cf2, [](const auto&, const auto&) {});
#endif
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) 2025-2025 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)
// Test from https://github.com/boostorg/pfr/issues/173
#include <boost/pfr/core.hpp>
#include <boost/pfr/core_name.hpp>
#include <boost/pfr/traits.hpp>
#include <string_view>
struct LongPointerTest {
long* OwningThread;
};
struct VoidPointerTest {
void* OwningThread;
};
int main() {
static_assert(boost::pfr::get_name<0, LongPointerTest>() == "OwningThread");
// No known workaround for MSVC
#if !defined(_MSC_VER) || _MSC_VER > 1944
static_assert(boost::pfr::get_name<0, VoidPointerTest>() == "OwningThread");
#endif
}