Skip to content

Commit

Permalink
fix for cxx14 build
Browse files Browse the repository at this point in the history
  • Loading branch information
denzor200 committed Jun 26, 2023
1 parent 4a1defa commit e8e077c
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 67 deletions.
8 changes: 2 additions & 6 deletions include/boost/pfr/core_name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,24 @@
#include <boost/pfr/detail/make_integer_sequence.hpp>

#include <cstddef>
#include <string_view>

#include <boost/pfr/tuple_size.hpp>

namespace boost { namespace pfr {

template <std::size_t I, class T>
constexpr std::string_view get_name() noexcept {
static_assert(sizeof(T) && BOOST_PFR_ENABLE_GETTING_NAMES, "====================> Boost.PFR: Calling boost::pfr::get_name is allowed only in C++20");
constexpr auto get_name() noexcept {
return detail::sequence_tuple::get<I>( detail::tie_as_names_tuple<T>() );
}

// FIXME: implement this
// template<class U, class T>
// constexpr std::string_view get_name() noexcept {
// static_assert(sizeof(T) && BOOST_PFR_ENABLE_GETTING_NAMES, "====================> Boost.PFR: Calling boost::pfr::get_name is allowed only in C++20");
// constexpr auto get_name() noexcept {
// return detail::sequence_tuple::get_by_type_impl<U>( detail::tie_as_names_tuple<T>() );
// }

template <class T>
constexpr auto names_as_array() noexcept {
static_assert(sizeof(T) && BOOST_PFR_ENABLE_GETTING_NAMES, "====================> Boost.PFR: Calling boost::pfr::names_as_array is allowed only in C++20");
return detail::make_stdarray_from_tietuple(
detail::tie_as_names_tuple<T>(),
detail::make_index_sequence< tuple_size_v<T> >()
Expand Down
66 changes: 8 additions & 58 deletions include/boost/pfr/detail/core_name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,67 +13,17 @@
#pragma once

#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/core.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <type_traits>
#include <string_view>
#include <array>

namespace boost { namespace pfr { namespace detail {

// TODO: move it outside
template <class... Args>
constexpr auto make_sequence_tuple(Args... args) noexcept {
return sequence_tuple::tuple<Args...>{ args... };
}

template <auto& ptr>
constexpr auto name_of_field_impl() noexcept {
#ifdef _MSC_VER
constexpr std::string_view sv = __FUNCSIG__;
constexpr auto last = sv.find_last_not_of(" >(", sv.size() - 6);
// Each core_name provides `TODO:` and
// `TODO:` functions.
//
// The whole functional of extracting field's names is build on top of those
// two functions.
#if BOOST_PFR_ENABLE_GETTING_NAMES
#include <boost/pfr/detail/core_name20_static.hpp>
#else
constexpr std::string_view sv = __PRETTY_FUNCTION__;
constexpr auto last = sv.find_last_not_of(" ])");
#include <boost/pfr/detail/core_name14_disabled.hpp>
#endif
constexpr auto first = sv.find_last_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789", last);
std::array<char, last - first + 1> res{};
auto it = res.data();
for (auto a = first+1; a <= last; ++a)
*it++ = sv[a];
return res;
}

template <typename T>
extern const T fake_object;

template <class T, std::size_t I>
constexpr auto stored_name_of_field = name_of_field_impl<detail::sequence_tuple::get<I>(
detail::tie_as_tuple(fake_object<T>)
)>();

template <class T, std::size_t... I>
constexpr auto tie_as_names_tuple_impl(std::index_sequence<I...>) noexcept {
return detail::make_sequence_tuple(std::string_view{stored_name_of_field<T, I>.data()}...);
}

template <class T>
constexpr auto tie_as_names_tuple() noexcept {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
static_assert(
sizeof(T) && BOOST_PFR_USE_CPP17,
"====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
);

return tie_as_names_tuple_impl<T>(detail::make_index_sequence<detail::fields_count<T>()>{});
}

}}}

#endif // BOOST_PFR_DETAIL_CORE_NAME_HPP

40 changes: 40 additions & 0 deletions include/boost/pfr/detail/core_name14_disabled.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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_CORE_NAME14_DISABLED_HPP
#define BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP
#pragma once

#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>

namespace boost { namespace pfr { namespace detail {

// TODO: move it outside
template <class... Args>
constexpr auto make_sequence_tuple(Args... args) noexcept {
return sequence_tuple::tuple<Args...>{ args... };
}


template <class T>
constexpr auto tie_as_names_tuple() noexcept {
static_assert(
sizeof(T) && false,
"====================> Boost.PFR: Extraction of field's names is allowed only in C++20"
);

return detail::make_sequence_tuple();
}

}}}

#endif // BOOST_PFR_DETAIL_CORE_NAME14_DISABLED_HPP

79 changes: 79 additions & 0 deletions include/boost/pfr/detail/core_name20_static.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// 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_CORE_NAME20_STATIC_HPP
#define BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP
#pragma once

#include <boost/pfr/detail/config.hpp>
#include <boost/pfr/detail/core.hpp>
#include <boost/pfr/detail/sequence_tuple.hpp>
#include <boost/pfr/detail/make_integer_sequence.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <type_traits>
#include <string_view>
#include <array>

namespace boost { namespace pfr { namespace detail {

// TODO: move it outside
template <class... Args>
constexpr auto make_sequence_tuple(Args... args) noexcept {
return sequence_tuple::tuple<Args...>{ args... };
}

template <auto& ptr>
constexpr auto name_of_field_impl() noexcept {
#ifdef _MSC_VER
constexpr std::string_view sv = __FUNCSIG__;
constexpr auto last = sv.find_last_not_of(" >(", sv.size() - 6);
#else
constexpr std::string_view sv = __PRETTY_FUNCTION__;
constexpr auto last = sv.find_last_not_of(" ])");
#endif
constexpr auto first = sv.find_last_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789", last);
std::array<char, last - first + 1> res{};
auto it = res.data();
for (auto a = first+1; a <= last; ++a)
*it++ = sv[a];
return res;
}

template <typename T>
extern const T fake_object;

template <class T, std::size_t I>
constexpr auto stored_name_of_field = name_of_field_impl<detail::sequence_tuple::get<I>(
detail::tie_as_tuple(fake_object<T>)
)>();

template <class T, std::size_t... I>
constexpr auto tie_as_names_tuple_impl(std::index_sequence<I...>) noexcept {
return detail::make_sequence_tuple(std::string_view{stored_name_of_field<T, I>.data()}...);
}

template <class T>
constexpr auto tie_as_names_tuple() noexcept {
static_assert(
!std::is_union<T>::value,
"====================> Boost.PFR: For safety reasons it is forbidden to reflect unions. See `Reflection of unions` section in the docs for more info."
);
static_assert(
sizeof(T) && BOOST_PFR_USE_CPP17,
"====================> Boost.PFR: Extraction of field's names is allowed only when the BOOST_PFR_USE_CPP17 macro enabled."
);

return tie_as_names_tuple_impl<T>(detail::make_index_sequence<detail::fields_count<T>()>{});
}

}}}

#endif // BOOST_PFR_DETAIL_CORE_NAME20_STATIC_HPP

11 changes: 8 additions & 3 deletions include/boost/pfr/detail/stdarray.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// Copyright (c) 2023 Denis Mikhailov
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
Expand All @@ -12,16 +11,22 @@

#include <utility> // metaprogramming stuff
#include <tuple>
#include <type_traits> // for std::common_type_t

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

namespace boost { namespace pfr { namespace detail {

template <class... Types>
constexpr auto make_stdarray(const Types&... t) noexcept {
return std::array<std::common_type_t<Types...>, sizeof...(Types)>{t...};
}

template <class T, std::size_t... I>
constexpr auto make_stdarray_from_tietuple(const T& t, std::index_sequence<I...>) noexcept {
return std::array{
return make_stdarray(
boost::pfr::detail::sequence_tuple::get<I>(t)...
};
);
}

}}}
Expand Down

0 comments on commit e8e077c

Please sign in to comment.