Skip to content

Commit

Permalink
Improve diagnostic for attempt to use get_name with non-external (#146
Browse files Browse the repository at this point in the history
)

Co-authored-by: Antony Polukhin <[email protected]>
  • Loading branch information
denzor200 and apolukhin authored Nov 26, 2023
1 parent 294a497 commit c695aa0
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 4 deletions.
2 changes: 2 additions & 0 deletions example/quick_examples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ void test_examples() {
// Disabled from testing since it's unportable
#if 0
{
// Keep in mind that it's unportable code
// You should move this structure somewhere outside of function scope
//[pfr_quick_examples_get_name
// Get name of field by index

Expand Down
4 changes: 2 additions & 2 deletions include/boost/pfr/detail/core_name20_static.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ consteval auto name_of_field() noexcept {
&& std::string_view{
detail::name_of_field_impl<
core_name_skip, detail::make_clang_wrapper(std::addressof(
fake_object<core_name_skip>.size_at_begin
detail::fake_object<core_name_skip>().size_at_begin
))
>().data()
} == "size_at_begin",
Expand All @@ -187,7 +187,7 @@ consteval auto name_of_field() noexcept {
template <class T, std::size_t I>
inline constexpr auto stored_name_of_field = detail::name_of_field<T,
detail::make_clang_wrapper(std::addressof(detail::sequence_tuple::get<I>(
detail::tie_as_tuple(detail::fake_object<T>)
detail::tie_as_tuple(detail::fake_object<T>())
)))
>();

Expand Down
13 changes: 12 additions & 1 deletion include/boost/pfr/detail/fake_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,19 @@

namespace boost { namespace pfr { namespace detail {

// This variable serves as a compile-time assert. If you see any error here, then
// you're probably using `boost::pfr::get_name()` or `boost::pfr::names_as_array()` with a non-external linkage type.
template <class T>
extern const T fake_object;
extern const T passed_type_has_no_external_linkage;

// For returning non default constructible types, it's exclusively used in member name retrieval.
//
// Neither std::declval nor boost::pfr::detail::unsafe_declval are usable there.
// Limitation - T should have external linkage.
template <class T>
constexpr const T& fake_object() noexcept {
return passed_type_has_no_external_linkage<T>;
}

}}} // namespace boost::pfr::detail

Expand Down
2 changes: 1 addition & 1 deletion test/core_name/print_name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ using namespace boost::pfr;
template <class T, std::size_t I>
inline constexpr auto no_check_stored_name_of_field = detail::name_of_field_impl<T,
detail::make_clang_wrapper(std::addressof(detail::sequence_tuple::get<I>(
detail::tie_as_tuple(detail::fake_object<T>)
detail::tie_as_tuple(detail::fake_object<T>())
)))
>();

Expand Down

0 comments on commit c695aa0

Please sign in to comment.