From 8794056e20f5f3efc373774bb5661216fd01e009 Mon Sep 17 00:00:00 2001 From: denzor200 Date: Sun, 10 Sep 2023 01:22:14 +0300 Subject: [PATCH] review --- doc/pfr.qbk | 24 +++++++-------- example/get_name.cpp | 4 +-- include/boost/pfr/config.hpp | 14 +++++---- include/boost/pfr/core_name.hpp | 15 ++++++++-- include/boost/pfr/detail/core_name.hpp | 2 +- .../boost/pfr/detail/core_name20_static.hpp | 29 +++++++++---------- include/boost/pfr/detail/fake_object.hpp | 25 ++++++++++++++++ include/boost/pfr/detail/sequence_tuple.hpp | 3 ++ include/boost/pfr/detail/stdarray.hpp | 7 ++++- test/config/print_config.cpp | 2 +- test/core_name/Jamfile.v2 | 28 +++++++++--------- .../fields_names_disabled_via_macro_00.cpp | 20 +++++++++++++ .../fields_names_disabled_via_macro_01.cpp | 20 +++++++++++++ .../fields_names_get_name_on_union.cpp | 22 ++++++++++++++ .../fields_names_names_as_array_on_union.cpp | 22 ++++++++++++++ test/core_name/{ => run}/fields_names.cpp | 8 +++++ .../{ => run}/fields_names_constexpr.cpp | 0 ...ds_names_correctly_configured_compiler.cpp | 0 .../fields_names_internal_parser.cpp | 2 +- .../generate_fields_names_big.cpp.py | 0 .../generate_fields_names_nonascii.cpp.py | 0 21 files changed, 192 insertions(+), 55 deletions(-) create mode 100644 include/boost/pfr/detail/fake_object.hpp create mode 100644 test/core_name/compile-fail/fields_names_disabled_via_macro_00.cpp create mode 100644 test/core_name/compile-fail/fields_names_disabled_via_macro_01.cpp create mode 100644 test/core_name/compile-fail/fields_names_get_name_on_union.cpp create mode 100644 test/core_name/compile-fail/fields_names_names_as_array_on_union.cpp rename test/core_name/{ => run}/fields_names.cpp (89%) rename test/core_name/{ => run}/fields_names_constexpr.cpp (100%) rename test/core_name/{ => run}/fields_names_correctly_configured_compiler.cpp (100%) rename test/core_name/{ => run}/fields_names_internal_parser.cpp (97%) rename test/core_name/{ => run}/generate_fields_names_big.cpp.py (100%) rename test/core_name/{ => run}/generate_fields_names_nonascii.cpp.py (100%) diff --git a/doc/pfr.qbk b/doc/pfr.qbk index 7341a5b3..f9e8e722 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -522,7 +522,7 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d [[*BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE*] [Define to `0` if you are hit by the template instantiation depth issues with `std::make_integer_sequence` and wish to use Boost.PFR version of that metafunction. Define to `1` to override Boost.PFR detection logic. ]] [[*BOOST_PFR_HAS_GUARANTEED_COPY_ELISION*] [Define to `0` if your compiler does not implement C++17 guaranteed copy elision properly and fails to reflect aggregates with non-movable fields. Define to `1` to override Boost.PFR detection logic. ]] [[*BOOST_PFR_ENABLE_IMPLICIT_REFLECTION*] [Define to `0` if you are hit by lots of non-effective choices made by implicitly reflection. Define to `1` to override Boost.PFR detection logic. ]] - [[*BOOST_PFR_ENABLE_GET_NAME_STATIC*] [On platforms where field's names extracting is not supported, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_ENABLE_GET_NAME_STATIC macro equal to 0. Defining this macro as 0 before including the header disables the ability to get a field's name. ]] + [[*BOOST_PFR_CORE_NAME_ENABLED*] [On platforms where field's names extracting is not supported, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_CORE_NAME_ENABLED macro equal to 0. Defining this macro as 0 before including the header disables the ability to get a field's name. ]] [[*BOOST_PFR_FUNCTION_SIGNATURE*] [On platforms which are unknown by Boost.PFR library, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_FUNCTION_SIGNATURE macro equal to "". Defining this macro before including the header might help the library to work on your specific platform. See details [link boost_pfr.limitations_of_field_names_refle [*here]]. ]] [[*BOOST_PFR_CORE_NAME_PARSING*] [On platforms which are unknown by Boost.PFR library, the 'boost/pfr/config.hpp' header defines the BOOST_PFR_CORE_NAME_PARSING macro equal to (0,0,false). Defining this macro before including the header might help the library to work on your specific platform. See details [link boost_pfr.limitations_of_field_names_refle [*here]]. ]] [[*BOOST_PFR_ENABLED*] [On platforms where Boost.PFR is not supported, the `boost/pfr/config.hpp` header defines the BOOST_PFR_ENABLED macro equal to 0. Defining this macro as 0 before including the header disables the Boost.PFR library. ]] @@ -556,13 +556,13 @@ Boost.PFRs extraction of field name has been tested and successfully work on man [section Define the BOOST_PFR_FUNCTION_SIGNATURE macro] If you get the following error during compilation -`` - PFRs extraction of field name could not detect your compiler. - Please make the BOOST_PFR_FUNCTION_SIGNATURE macro use - correct compiler macro for getting the whole function name. - Define BOOST_PFR_CORE_NAME_PARSING to correct value after that. -`` -then you are using a compiler that was not tested with this library. +``` +error: static_assert failed "====================> Boost.PFR: Extraction of field name could not detect your compiler. + Please make the BOOST_PFR_FUNCTION_SIGNATURE macro use + correct compiler macro for getting the whole function name. + Define BOOST_PFR_CORE_NAME_PARSING to correct value after that." +``` +then you are using a compiler that was not tested with this library. BOOST_PFR_FUNCTION_SIGNATURE must be defined to a compiler specific macro, that outputs the *whole* function signature including non-type template parameters. @@ -574,8 +574,8 @@ function signature including non-type template parameters. Let's assume the structure `namespace A { struct A { int fn; }; }` -If the output of `boost::pfr::get_name<0, A::A>()` -returns not just `fn` but also a lot of text around the `fn` +If the output of `boost::pfr::get_name<0, A::A>()` +returns not just `fn` but also a lot of text around the `fn` or does not return name at all then you are using a compiler that was not tested with this library and you need to setup the BOOST_PFR_CORE_NAME_PARSING macro. @@ -583,9 +583,9 @@ BOOST_PFR_CORE_NAME_PARSING macro. Here is a short instruction: # get the output of `boost::pfr::get_name<0, A::A>()` -# define BOOST_PFR_CORE_NAME_PARSING to +# define BOOST_PFR_CORE_NAME_PARSING to `(skip_at_begin, skip_at_end, false, "")`, where - * `skip_at_begin` is equal to characters count before the first occurrence of `fn` in output + * `skip_at_begin` is equal to characters count before the first occurrence of `fn` in output * `skip_at_end` is equal to characters count after last occurrence of `fn` in output # check that `boost::pfr::get_name<0, A::A>()` returns "fn" # if it does not return `fn`, then define BOOST_PFR_CORE_NAME_PARSING to diff --git a/example/get_name.cpp b/example/get_name.cpp index 0b5bf2b9..5f5c7eb3 100644 --- a/example/get_name.cpp +++ b/example/get_name.cpp @@ -10,7 +10,7 @@ #include -#if BOOST_PFR_ENABLE_GET_NAME_STATIC && BOOST_PFR_USE_CPP17 +#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17 //[pfr_example_get_name /*` Since C++20 it's possible to read name of structure fields by index using Boost.PFR library. @@ -34,7 +34,7 @@ constexpr auto r2 = boost::pfr::get_name<1, foo>(); // reading name of field wit #endif int main() { -#if BOOST_PFR_ENABLE_GET_NAME_STATIC && BOOST_PFR_USE_CPP17 +#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17 if (r1 != "some_integer") return 1; if (r2 != "c") return 2; #endif diff --git a/include/boost/pfr/config.hpp b/include/boost/pfr/config.hpp index b9ab97f2..faa66894 100644 --- a/include/boost/pfr/config.hpp +++ b/include/boost/pfr/config.hpp @@ -98,12 +98,16 @@ # endif #endif -#ifndef BOOST_PFR_ENABLE_GET_NAME_STATIC -# if (defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911) \ - || (__cplusplus >= 202002L && defined(__clang_major__) && __clang_major__ >= 12) -# define BOOST_PFR_ENABLE_GET_NAME_STATIC 1 +#ifndef BOOST_PFR_CORE_NAME_ENABLED +# if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L)) +# if (defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911) \ + || (defined(__clang_major__) && __clang_major__ >= 12) +# define BOOST_PFR_CORE_NAME_ENABLED 1 +# else +# define BOOST_PFR_CORE_NAME_ENABLED 0 +# endif # else -# define BOOST_PFR_ENABLE_GET_NAME_STATIC 0 +# define BOOST_PFR_CORE_NAME_ENABLED 0 # endif #endif diff --git a/include/boost/pfr/core_name.hpp b/include/boost/pfr/core_name.hpp index d6402f5f..1103af91 100644 --- a/include/boost/pfr/core_name.hpp +++ b/include/boost/pfr/core_name.hpp @@ -20,7 +20,8 @@ #include #include -#include +#include // for std::size_t +#include // for std::enable_if_t #include @@ -74,13 +75,23 @@ std::array> #else auto #endif -names_as_array() noexcept { +names_as_array( +#ifndef BOOST_PFR_DOXYGEN_INVOKED + std::enable_if_t())::empty()>* = nullptr +#endif + ) noexcept { return detail::make_stdarray_from_tietuple( detail::tie_as_names_tuple(), detail::make_index_sequence< tuple_size_v >() ); } +#ifndef BOOST_PFR_DOXYGEN_INVOKED +template +constexpr auto names_as_array(std::enable_if_t())::empty()>* = nullptr) noexcept { + return detail::make_empty_stdarray(); +} +#endif }} // namespace boost::pfr diff --git a/include/boost/pfr/detail/core_name.hpp b/include/boost/pfr/detail/core_name.hpp index 10e59830..f266ef20 100644 --- a/include/boost/pfr/detail/core_name.hpp +++ b/include/boost/pfr/detail/core_name.hpp @@ -19,7 +19,7 @@ // // The whole functional of extracting field's names is build on top of those // two functions. -#if BOOST_PFR_ENABLE_GET_NAME_STATIC +#if BOOST_PFR_CORE_NAME_ENABLED #include #else #include diff --git a/include/boost/pfr/detail/core_name20_static.hpp b/include/boost/pfr/detail/core_name20_static.hpp index 9d0dc37e..78e1abff 100644 --- a/include/boost/pfr/detail/core_name20_static.hpp +++ b/include/boost/pfr/detail/core_name20_static.hpp @@ -18,10 +18,12 @@ #include #include #include +#include #include #include #include #include // for std::ranges::copy +#include // for std::addressof namespace boost { namespace pfr { namespace detail { @@ -62,7 +64,7 @@ struct backward { explicit consteval backward(std::string_view value) noexcept : value(value) {} - + std::string_view value; }; @@ -93,7 +95,7 @@ template consteval void assert_compile_time_legths() noexcept { static_assert( Condition, - "PFRs extraction of field name is misconfigured for your compiler. " + "====================> Boost.PFR: Extraction of field name is misconfigured for your compiler. " "Please define BOOST_PFR_CORE_NAME_PARSING to correct values. See section " "Limitations of field's names reflection' of the documentation for more information." ); @@ -103,7 +105,7 @@ template consteval void failed_to_get_function_name() noexcept { static_assert( sizeof(T) && false, - "PFRs extraction of field name could not detect your compiler. " + "====================> Boost.PFR: Extraction of field name could not detect your compiler. " "Please make the BOOST_PFR_FUNCTION_SIGNATURE macro use " "correct compiler macro for getting the whole function name. " "Define BOOST_PFR_CORE_NAME_PARSING to correct value after that." @@ -118,7 +120,7 @@ consteval std::string_view clang_workaround(std::string_view value) noexcept return value; } -template +template consteval auto name_of_field_impl() noexcept { constexpr std::string_view sv = detail::clang_workaround(BOOST_PFR_FUNCTION_SIGNATURE); if constexpr (sv.empty()) { @@ -141,32 +143,29 @@ consteval auto name_of_field_impl() noexcept { } } -template -extern const T fake_object; - #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundefined-var-template" -// clang 16 doesn't support address of non-static member as template parameter +// clang 16 and earlier don't support address of non-static member as template parameter // but fortunately it's possible to use C++20 non-type template parameters in another way // even in clang 16 and more older clangs // all we need is to wrap pointer into 'clang_wrapper_t' and then pass it into template -template +template struct clang_wrapper_t { T v; }; -template +template clang_wrapper_t(T) -> clang_wrapper_t; -template +template constexpr auto make_clang_wrapper(const T& arg) noexcept { return clang_wrapper_t{arg}; } #else -template +template constexpr const T& make_clang_wrapper(const T& arg) noexcept { // It's everything OK with address of non-static member as template parameter support on this compiler // so we don't need a wrapper here, just pass the pointer into template @@ -178,9 +177,9 @@ constexpr const T& make_clang_wrapper(const T& arg) noexcept { // Without passing 'T' into 'name_of_field_impl' different fields from different structures might have the same name! // See https://developercommunity.visualstudio.com/t/__FUNCSIG__-outputs-wrong-value-with-C/10458554 for details template -constexpr auto stored_name_of_field = name_of_field_impl( +constexpr auto stored_name_of_field = detail::name_of_field_impl( detail::tie_as_tuple(fake_object) -))>(); +)))>(); #ifdef __clang__ #pragma clang diagnostic pop @@ -216,7 +215,7 @@ constexpr auto tie_as_names_tuple() noexcept { "====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled." ); - return tie_as_names_tuple_impl(detail::make_index_sequence()>{}); + return detail::tie_as_names_tuple_impl(detail::make_index_sequence()>{}); } }}} // namespace boost::pfr::detail diff --git a/include/boost/pfr/detail/fake_object.hpp b/include/boost/pfr/detail/fake_object.hpp new file mode 100644 index 00000000..2e37e978 --- /dev/null +++ b/include/boost/pfr/detail/fake_object.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. +// +// 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) + + +// Initial implementation by Bela Schaum, https://github.com/schaumb +// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 +// + +#ifndef BOOST_PFR_DETAIL_FAKE_OBJECT_HPP +#define BOOST_PFR_DETAIL_FAKE_OBJECT_HPP +#pragma once + +#include + +namespace boost { namespace pfr { namespace detail { + +template +extern const T fake_object; + +}}} // namespace boost::pfr::detail + +#endif // BOOST_PFR_DETAIL_FAKE_OBJECT_HPP + diff --git a/include/boost/pfr/detail/sequence_tuple.hpp b/include/boost/pfr/detail/sequence_tuple.hpp index 07ba4627..fcbb8370 100644 --- a/include/boost/pfr/detail/sequence_tuple.hpp +++ b/include/boost/pfr/detail/sequence_tuple.hpp @@ -127,6 +127,9 @@ struct tuple: tuple_base< detail::index_sequence_for, Values... >::tuple_base; + + constexpr static std::size_t size() noexcept { return sizeof...(Values); } + constexpr static bool empty() noexcept { return size() == 0; } }; diff --git a/include/boost/pfr/detail/stdarray.hpp b/include/boost/pfr/detail/stdarray.hpp index dce7c871..d6de1ea2 100644 --- a/include/boost/pfr/detail/stdarray.hpp +++ b/include/boost/pfr/detail/stdarray.hpp @@ -10,8 +10,9 @@ #include #include // metaprogramming stuff -#include +#include #include // for std::common_type_t +#include #include @@ -29,6 +30,10 @@ constexpr auto make_stdarray_from_tietuple(const T& t, std::index_sequence ); } +constexpr auto make_empty_stdarray() noexcept { + return std::array{}; +} + }}} // namespace boost::pfr::detail #endif // BOOST_PFR_DETAIL_STDARRAY_HPP diff --git a/test/config/print_config.cpp b/test/config/print_config.cpp index 2b0dc6a4..b9c0e77e 100644 --- a/test/config/print_config.cpp +++ b/test/config/print_config.cpp @@ -15,7 +15,7 @@ int main() { << "BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == " << BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE << '\n' << "BOOST_PFR_HAS_GUARANTEED_COPY_ELISION == " << BOOST_PFR_HAS_GUARANTEED_COPY_ELISION << '\n' << "BOOST_PFR_ENABLE_IMPLICIT_REFLECTION == " << BOOST_PFR_ENABLE_IMPLICIT_REFLECTION << '\n' - << "BOOST_PFR_ENABLE_GET_NAME_STATIC == " << BOOST_PFR_ENABLE_GET_NAME_STATIC << '\n' + << "BOOST_PFR_CORE_NAME_ENABLED == " << BOOST_PFR_CORE_NAME_ENABLED << '\n' << "BOOST_PFR_FUNCTION_SIGNATURE == " << BOOST_PP_STRINGIZE(BOOST_PFR_FUNCTION_SIGNATURE) << '\n' << "BOOST_PFR_CORE_NAME_PARSING == " << BOOST_PP_STRINGIZE(BOOST_PFR_CORE_NAME_PARSING) << '\n' << "BOOST_PFR_ENABLED == " << BOOST_PFR_ENABLED << '\n' diff --git a/test/core_name/Jamfile.v2 b/test/core_name/Jamfile.v2 index b659ca7f..5d29178f 100644 --- a/test/core_name/Jamfile.v2 +++ b/test/core_name/Jamfile.v2 @@ -43,9 +43,6 @@ project [ check-target-builds ../core_name//compiler_supports_cxx20_address_of_non_static_member_tplarg : : [ check-target-builds ../core_name//compiler_supports_cxx20_nontype_tplarg : : no ] ] ; -local ENABLED_ENGINE = BOOST_PFR_ENABLE_GET_NAME_STATIC=1 ; -local DISABLED_ENGINE = BOOST_PFR_ENABLE_GET_NAME_STATIC=0 ; - actions invoke_python_generator @@ -53,25 +50,26 @@ actions invoke_python_generator python $(>) > $(<) } -make fields_names_nonascii.cpp : generate_fields_names_nonascii.cpp.py : @invoke_python_generator ; -make fields_names_big.cpp : generate_fields_names_big.cpp.py : @invoke_python_generator ; - test-suite pfr_name_tests : - [ run fields_names.cpp : : : : ] - [ run fields_names_constexpr.cpp : : : : ] - [ run fields_names_nonascii.cpp : : : msvc:"/utf-8" : ] - [ run fields_names_big.cpp : : : msvc:"/bigobj" : ] - [ run fields_names_correctly_configured_compiler.cpp : : : : ] - [ run fields_names_internal_parser.cpp : : : : ] [ run print_name.cpp : : : always_show_run_output ] ; +for local source_file in [ glob ./run/*.cpp ] +{ + pfr_name_tests += [ run $(source_file) : : : : ] ; +} + +for local source_file in [ glob ./run/*.py ] +{ + local cpp_source_file = $(source_file[1]:B) ; + make $(cpp_source_file) : $(source_file) : @invoke_python_generator ; + pfr_name_tests += [ run $(cpp_source_file) : : : msvc:"/utf-8" msvc:"/bigobj" : ] ; +} + for local source_file in [ glob ./compile-fail/*.cpp ] { - local target_name = $(source_file[1]:B) ; - pfr_name_tests += [ compile-fail $(source_file) : $(ENABLED_ENGINE) : $(target_name)_on ] ; - pfr_name_tests += [ compile-fail $(source_file) : $(DISABLED_ENGINE) : $(target_name)_off ] ; + pfr_name_tests += [ compile-fail $(source_file) : : ] ; } diff --git a/test/core_name/compile-fail/fields_names_disabled_via_macro_00.cpp b/test/core_name/compile-fail/fields_names_disabled_via_macro_00.cpp new file mode 100644 index 00000000..7cda619b --- /dev/null +++ b/test/core_name/compile-fail/fields_names_disabled_via_macro_00.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. +// +// 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) + + +// Initial implementation by Bela Schaum, https://github.com/schaumb +// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 +// + +#define BOOST_PFR_CORE_NAME_ENABLED 0 +#include + +struct A { int field; }; + +int main() { + (void)boost::pfr::get_name<0, A>(); // Must be a compile time error +} + + diff --git a/test/core_name/compile-fail/fields_names_disabled_via_macro_01.cpp b/test/core_name/compile-fail/fields_names_disabled_via_macro_01.cpp new file mode 100644 index 00000000..392e3979 --- /dev/null +++ b/test/core_name/compile-fail/fields_names_disabled_via_macro_01.cpp @@ -0,0 +1,20 @@ +// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. +// +// 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) + + +// Initial implementation by Bela Schaum, https://github.com/schaumb +// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 +// + +#define BOOST_PFR_CORE_NAME_ENABLED 0 +#include + +struct A { int field; }; + +int main() { + (void)boost::pfr::names_as_array(); // Must be a compile time error +} + + diff --git a/test/core_name/compile-fail/fields_names_get_name_on_union.cpp b/test/core_name/compile-fail/fields_names_get_name_on_union.cpp new file mode 100644 index 00000000..e4f9e633 --- /dev/null +++ b/test/core_name/compile-fail/fields_names_get_name_on_union.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. +// +// 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) + + +// Initial implementation by Bela Schaum, https://github.com/schaumb +// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 +// + +#include + +union test_union { + const char* c; + int i; +}; + +int main() { + (void)boost::pfr::get_name<0, test_union>(); // Must be a compile time error +} + + diff --git a/test/core_name/compile-fail/fields_names_names_as_array_on_union.cpp b/test/core_name/compile-fail/fields_names_names_as_array_on_union.cpp new file mode 100644 index 00000000..d61dd0d7 --- /dev/null +++ b/test/core_name/compile-fail/fields_names_names_as_array_on_union.cpp @@ -0,0 +1,22 @@ +// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. +// +// 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) + + +// Initial implementation by Bela Schaum, https://github.com/schaumb +// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 +// + +#include + +union test_union { + const char* c; + int i; +}; + +int main() { + (void)boost::pfr::names_as_array(); // Must be a compile time error +} + + diff --git a/test/core_name/fields_names.cpp b/test/core_name/run/fields_names.cpp similarity index 89% rename from test/core_name/fields_names.cpp rename to test/core_name/run/fields_names.cpp index 0d0fad2b..ca7acbdf 100644 --- a/test/core_name/fields_names.cpp +++ b/test/core_name/run/fields_names.cpp @@ -32,6 +32,8 @@ struct A { int second; }; +struct empty {}; + void test_get_name_by_id() { BOOST_TEST_EQ( ((boost::pfr::get_name<0, Aggregate>())), "member1"); BOOST_TEST_EQ( ((boost::pfr::get_name<1, Aggregate>())), "this_is_a_name"); @@ -64,6 +66,11 @@ void test_names_as_array() { } } +void test_names_as_array_for_empty() { + const auto value = boost::pfr::names_as_array(); + BOOST_TEST_EQ(value.size(), 0); + BOOST_TEST_EQ(value.empty(), true); +} } // namespace testing @@ -71,6 +78,7 @@ int main() { testing::test_get_name_by_id(); testing::test_get_name_by_type(); testing::test_names_as_array(); + testing::test_names_as_array_for_empty(); return boost::report_errors(); } diff --git a/test/core_name/fields_names_constexpr.cpp b/test/core_name/run/fields_names_constexpr.cpp similarity index 100% rename from test/core_name/fields_names_constexpr.cpp rename to test/core_name/run/fields_names_constexpr.cpp diff --git a/test/core_name/fields_names_correctly_configured_compiler.cpp b/test/core_name/run/fields_names_correctly_configured_compiler.cpp similarity index 100% rename from test/core_name/fields_names_correctly_configured_compiler.cpp rename to test/core_name/run/fields_names_correctly_configured_compiler.cpp diff --git a/test/core_name/fields_names_internal_parser.cpp b/test/core_name/run/fields_names_internal_parser.cpp similarity index 97% rename from test/core_name/fields_names_internal_parser.cpp rename to test/core_name/run/fields_names_internal_parser.cpp index bf98287c..b4d5802b 100644 --- a/test/core_name/fields_names_internal_parser.cpp +++ b/test/core_name/run/fields_names_internal_parser.cpp @@ -16,7 +16,7 @@ namespace testing { -constexpr std::string_view fake_func_name = " ******************** [fake_text1->fake_text2->fake_text3] **********"; +constexpr std::string_view fake_func_name = " ******************** [fake_text1->fake_text2->fake_text3] **********"; void test_general() { diff --git a/test/core_name/generate_fields_names_big.cpp.py b/test/core_name/run/generate_fields_names_big.cpp.py similarity index 100% rename from test/core_name/generate_fields_names_big.cpp.py rename to test/core_name/run/generate_fields_names_big.cpp.py diff --git a/test/core_name/generate_fields_names_nonascii.cpp.py b/test/core_name/run/generate_fields_names_nonascii.cpp.py similarity index 100% rename from test/core_name/generate_fields_names_nonascii.cpp.py rename to test/core_name/run/generate_fields_names_nonascii.cpp.py