diff options
author | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
---|---|---|
committer | max42 <max42@yandex-team.com> | 2023-06-30 03:37:03 +0300 |
commit | fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a (patch) | |
tree | b8cbc1deb00309c7f1a7ab6df520a76cf0b5c6d7 /contrib/libs/pfr | |
parent | 7bf166b1a7ed0af927f230022b245af618e998c1 (diff) | |
download | ydb-fac2bd72b4b31ec3238292caf8fb2a8aaa6d6c4a.tar.gz |
YT-19324: move YT provider to ydb/library/yql
This commit is formed by the following script: https://paste.yandex-team.ru/6f92e4b8-efc5-4d34-948b-15ee2accd7e7/text.
This commit has zero effect on all projects that depend on YQL.
The summary of changes:
- `yql/providers/yt -> ydb/library/yql/providers/yt `- the whole implementation of YT provider is moved into YDB code base for further export as a part of YT YQL plugin shared library;
- `yql/providers/stat/{expr_nodes,uploader} -> ydb/library/yql/providers/stat/{expr_nodes,uploader}` - a small interface without implementation and the description of stat expr nodes;
- `yql/core/extract_predicate/ut -> ydb/library/yql/core/extract_predicate/ut`;
- `yql/core/{ut,ut_common} -> ydb/library/yql/core/{ut,ut_common}`;
- `yql/core` is gone;
- `yql/library/url_preprocessing -> ydb/library/yql/core/url_preprocessing`.
**NB**: all new targets inside `ydb/` are under `IF (NOT CMAKE_EXPORT)` clause which disables them from open-source cmake generation and ya make build. They will be enabled in the subsequent commits.
Diffstat (limited to 'contrib/libs/pfr')
-rw-r--r-- | contrib/libs/pfr/LICENSE_1_0.txt | 23 | ||||
-rw-r--r-- | contrib/libs/pfr/README.md | 104 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/config.hpp | 91 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/fields_count.hpp | 330 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/make_integer_sequence.hpp | 90 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/sequence_tuple.hpp | 127 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/size_t_.hpp | 18 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/detail/unsafe_declval.hpp | 36 | ||||
-rw-r--r-- | contrib/libs/pfr/include/pfr/tuple_size.hpp | 48 | ||||
-rw-r--r-- | contrib/libs/pfr/ya.make | 20 |
10 files changed, 887 insertions, 0 deletions
diff --git a/contrib/libs/pfr/LICENSE_1_0.txt b/contrib/libs/pfr/LICENSE_1_0.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/contrib/libs/pfr/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/contrib/libs/pfr/README.md b/contrib/libs/pfr/README.md new file mode 100644 index 0000000000..0a83f4b983 --- /dev/null +++ b/contrib/libs/pfr/README.md @@ -0,0 +1,104 @@ +# [PFR](https://apolukhin.github.io/pfr_non_boost/) + +This is a C++14 library for very basic reflection that gives you access to structure elements by index and provides other `std::tuple` like methods for user defined types without any macro or boilerplate code. + +[Boost.PFR](https://boost.org/libs/pfr) is a part of the [Boost C++ Libraries](https://github.com/boostorg). However, Boost.PFR is a header only library that does not depend on Boost. You can just copy the content of the "include" folder from the github into your project, and the library will work fine. + +For a version of the library without `boost::` namespace see [PFR](https://github.com/apolukhin/pfr_non_boost). + +### Test results + +Branches | Build | Tests coverage | More info +----------------|-------------- | -------------- |----------- +Develop: | [![CI](https://github.com/boostorg/pfr/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/0mavmnkdmltcdmqa/branch/develop?svg=true)](https://ci.appveyor.com/project/apolukhin/pfr/branch/develop) | [![Coverage Status](https://coveralls.io/repos/github/apolukhin/magic_get/badge.png?branch=develop)](https://coveralls.io/github/apolukhin/magic_get?branch=develop) | [details...](https://www.boost.org/development/tests/develop/developer/pfr.html) +Master: | [![CI](https://github.com/boostorg/pfr/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/pfr/actions/workflows/ci.yml) [![Build status](https://ci.appveyor.com/api/projects/status/0mavmnkdmltcdmqa/branch/master?svg=true)](https://ci.appveyor.com/project/apolukhin/pfr/branch/master) | [![Coverage Status](https://coveralls.io/repos/github/apolukhin/magic_get/badge.png?branch=master)](https://coveralls.io/github/apolukhin/magic_get?branch=master) | [details...](https://www.boost.org/development/tests/master/developer/pfr.html) + +[Latest developer documentation](https://www.boost.org/doc/libs/develop/doc/html/boost_pfr.html) + +### Motivating Example #0 +```c++ +#include <iostream> +#include <fstream> +#include <string> + +#include "pfr.hpp" + +struct some_person { + std::string name; + unsigned birth_year; +}; + +int main(int argc, const char* argv[]) { + some_person val{"Edgar Allan Poe", 1809}; + + std::cout << pfr::get<0>(val) // No macro! + << " was born in " << pfr::get<1>(val); // Works with any aggregate initializables! + + if (argc > 1) { + std::ofstream ofs(argv[1]); + ofs << pfr::io(val); // File now contains: {"Edgar Allan Poe", 1809} + } +} +``` +Outputs: +``` +Edgar Allan Poe was born in 1809 +``` + + +### Motivating Example #1 +```c++ +#include <iostream> +#include "pfr/precise.hpp" + +struct my_struct { // no ostream operator defined! + int i; + char c; + double d; +}; + +int main() { + my_struct s{100, 'H', 3.141593}; + std::cout << "my_struct has " << pfr::tuple_size<my_struct>::value + << " fields: " << pfr::io(s) << "\n"; +} + +``` + +Outputs: +``` +my_struct has 3 fields: {100, H, 3.14159} +``` + +### Motivating Example #2 + +```c++ +#include <iostream> +#include "pfr/precise.hpp" + +struct my_struct { // no ostream operator defined! + std::string s; + int i; +}; + +int main() { + my_struct s{{"Das ist fantastisch!"}, 100}; + std::cout << "my_struct has " << pfr::tuple_size<my_struct>::value + << " fields: " << pfr::io(s) << "\n"; +} + +``` + +Outputs: +``` +my_struct has 2 fields: {"Das ist fantastisch!", 100} +``` + + +### Requirements and Limitations + +[See docs](https://www.boost.org/doc/libs/develop/doc/html/boost_pfr.html). + +### License + +Distributed under the [Boost Software License, Version 1.0](https://boost.org/LICENSE_1_0.txt). diff --git a/contrib/libs/pfr/include/pfr/detail/config.hpp b/contrib/libs/pfr/include/pfr/detail/config.hpp new file mode 100644 index 0000000000..ec2143d9ba --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/config.hpp @@ -0,0 +1,91 @@ +// Copyright (c) 2016-2021 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) + +#ifndef PFR_DETAIL_CONFIG_HPP +#define PFR_DETAIL_CONFIG_HPP +#pragma once + +#include <type_traits> // to get non standard platform macro definitions (__GLIBCXX__ for example) + +// Reminder: +// * MSVC++ 14.2 _MSC_VER == 1927 <- Loophole is known to work (Visual Studio ????) +// * MSVC++ 14.1 _MSC_VER == 1916 <- Loophole is known to NOT work (Visual Studio 2017) +// * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) +// * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) + +#if defined(_MSC_VER) +# if !defined(_MSVC_LANG) || _MSC_VER <= 1900 +# error Boost.PFR library requires more modern MSVC compiler. +# endif +#elif __cplusplus < 201402L +# error Boost.PFR library requires at least C++14. +#endif + +#ifndef PFR_USE_LOOPHOLE +# if defined(_MSC_VER) +# if _MSC_VER >= 1927 +# define PFR_USE_LOOPHOLE 1 +# else +# define PFR_USE_LOOPHOLE 0 +# endif +# elif defined(__clang_major__) && __clang_major__ >= 8 +# define PFR_USE_LOOPHOLE 0 +# else +# define PFR_USE_LOOPHOLE 1 +# endif +#endif + +#ifndef PFR_USE_CPP17 +# ifdef __cpp_structured_bindings +# define PFR_USE_CPP17 1 +# elif defined(_MSVC_LANG) +# if _MSVC_LANG >= 201703L +# define PFR_USE_CPP17 1 +# else +# define PFR_USE_CPP17 0 +# endif +# else +# define PFR_USE_CPP17 0 +# endif +#endif + +#if (!PFR_USE_CPP17 && !PFR_USE_LOOPHOLE) +# if (defined(_MSC_VER) && _MSC_VER < 1916) ///< in Visual Studio 2017 v15.9 PFR library with classic engine normally works +# error Boost.PFR requires /std:c++latest or /std:c++17 flags on your compiler. +# endif +#endif + +#ifndef PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE +// Assume that libstdc++ since GCC-7.3 does not have linear instantiation depth in std::make_integral_sequence +# if defined( __GLIBCXX__) && __GLIBCXX__ >= 20180101 +# define PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1 +# elif defined(_MSC_VER) +# define PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 1 +//# elif other known working lib +# else +# define PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE 0 +# endif +#endif + +#ifndef PFR_HAS_GUARANTEED_COPY_ELISION +# if defined(__cpp_guaranteed_copy_elision) && (!defined(_MSC_VER) || _MSC_VER > 1928) +# define PFR_HAS_GUARANTEED_COPY_ELISION 1 +# else +# define PFR_HAS_GUARANTEED_COPY_ELISION 0 +# endif +#endif + +#if defined(__has_cpp_attribute) +# if __has_cpp_attribute(maybe_unused) +# define PFR_MAYBE_UNUSED [[maybe_unused]] +# endif +#endif + +#ifndef PFR_MAYBE_UNUSED +# define PFR_MAYBE_UNUSED +#endif + + +#endif // PFR_DETAIL_CONFIG_HPP diff --git a/contrib/libs/pfr/include/pfr/detail/fields_count.hpp b/contrib/libs/pfr/include/pfr/detail/fields_count.hpp new file mode 100644 index 0000000000..d4ad82353a --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/fields_count.hpp @@ -0,0 +1,330 @@ +// Copyright (c) 2016-2021 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) + +#ifndef PFR_DETAIL_FIELDS_COUNT_HPP +#define PFR_DETAIL_FIELDS_COUNT_HPP +#pragma once + +#include <pfr/detail/config.hpp> +#include <pfr/detail/make_integer_sequence.hpp> +#include <pfr/detail/size_t_.hpp> +#include <pfr/detail/unsafe_declval.hpp> + +#include <climits> // CHAR_BIT +#include <type_traits> +#include <utility> // metaprogramming stuff + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wmissing-braces" +# pragma clang diagnostic ignored "-Wundefined-inline" +# pragma clang diagnostic ignored "-Wundefined-internal" +# pragma clang diagnostic ignored "-Wmissing-field-initializers" +#endif + +namespace pfr { namespace detail { + +///////////////////// Structure that can be converted to reference to anything +struct ubiq_lref_constructor { + std::size_t ignore; + template <class Type> constexpr operator Type&() const && noexcept { // tweak for template_unconstrained.cpp like cases + return detail::unsafe_declval<Type&>(); + } + + template <class Type> constexpr operator Type&() const & noexcept { // tweak for optional_chrono.cpp like cases + return detail::unsafe_declval<Type&>(); + } +}; + +///////////////////// Structure that can be converted to rvalue reference to anything +struct ubiq_rref_constructor { + std::size_t ignore; + template <class Type> /*constexpr*/ operator Type() const && noexcept { // Allows initialization of rvalue reference fields and move-only types + return detail::unsafe_declval<Type>(); + } +}; + + +#ifndef __cpp_lib_is_aggregate +///////////////////// Hand-made is_aggregate_initializable_n<T> trait + +// Structure that can be converted to reference to anything except reference to T +template <class T, bool IsCopyConstructible> +struct ubiq_constructor_except { + std::size_t ignore; + template <class Type> constexpr operator std::enable_if_t<!std::is_same<T, Type>::value, Type&> () const noexcept; // Undefined +}; + +template <class T> +struct ubiq_constructor_except<T, false> { + std::size_t ignore; + template <class Type> constexpr operator std::enable_if_t<!std::is_same<T, Type>::value, Type&&> () const noexcept; // Undefined +}; + + +// `std::is_constructible<T, ubiq_constructor_except<T>>` consumes a lot of time, so we made a separate lazy trait for it. +template <std::size_t N, class T> struct is_single_field_and_aggregate_initializable: std::false_type {}; +template <class T> struct is_single_field_and_aggregate_initializable<1, T>: std::integral_constant< + bool, !std::is_constructible<T, ubiq_constructor_except<T, std::is_copy_constructible<T>::value>>::value +> {}; + +// Hand-made is_aggregate<T> trait: +// Before C++20 aggregates could be constructed from `decltype(ubiq_?ref_constructor{I})...` but type traits report that +// there's no constructor from `decltype(ubiq_?ref_constructor{I})...` +// Special case for N == 1: `std::is_constructible<T, ubiq_?ref_constructor>` returns true if N == 1 and T is copy/move constructible. +template <class T, std::size_t N> +struct is_aggregate_initializable_n { + template <std::size_t ...I> + static constexpr bool is_not_constructible_n(std::index_sequence<I...>) noexcept { + return (!std::is_constructible<T, decltype(ubiq_lref_constructor{I})...>::value && !std::is_constructible<T, decltype(ubiq_rref_constructor{I})...>::value) + || is_single_field_and_aggregate_initializable<N, T>::value + ; + } + + static constexpr bool value = + std::is_empty<T>::value + || std::is_array<T>::value + || std::is_fundamental<T>::value + || is_not_constructible_n(detail::make_index_sequence<N>{}) + ; +}; + +#endif // #ifndef __cpp_lib_is_aggregate + +///////////////////// Detect aggregates with inheritance +template <class Derived, class U> +constexpr bool static_assert_non_inherited() noexcept { + static_assert( + !std::is_base_of<U, Derived>::value, + "====================> Boost.PFR: Boost.PFR: Inherited types are not supported." + ); + return true; +} + +template <class Derived> +struct ubiq_lref_base_asserting { + template <class Type> constexpr operator Type&() const && // tweak for template_unconstrained.cpp like cases + noexcept(detail::static_assert_non_inherited<Derived, Type>()) // force the computation of assert function + { + return detail::unsafe_declval<Type&>(); + } + + template <class Type> constexpr operator Type&() const & // tweak for optional_chrono.cpp like cases + noexcept(detail::static_assert_non_inherited<Derived, Type>()) // force the computation of assert function + { + return detail::unsafe_declval<Type&>(); + } +}; + +template <class Derived> +struct ubiq_rref_base_asserting { + template <class Type> /*constexpr*/ operator Type() const && // Allows initialization of rvalue reference fields and move-only types + noexcept(detail::static_assert_non_inherited<Derived, Type>()) // force the computation of assert function + { + return detail::unsafe_declval<Type>(); + } +}; + +template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = typename std::enable_if<std::is_copy_constructible<T>::value>::type> +constexpr auto assert_first_not_base(std::index_sequence<I0, I...>) noexcept + -> typename std::add_pointer<decltype(T{ ubiq_lref_base_asserting<T>{}, ubiq_lref_constructor{I}... })>::type +{ + return nullptr; +} + +template <class T, std::size_t I0, std::size_t... I, class /*Enable*/ = typename std::enable_if<!std::is_copy_constructible<T>::value>::type> +constexpr auto assert_first_not_base(std::index_sequence<I0, I...>) noexcept + -> typename std::add_pointer<decltype(T{ ubiq_rref_base_asserting<T>{}, ubiq_rref_constructor{I}... })>::type +{ + return nullptr; +} + +template <class T> +constexpr void* assert_first_not_base(std::index_sequence<>) noexcept +{ + return nullptr; +} + +///////////////////// Helper for SFINAE on fields count +template <class T, std::size_t... I, class /*Enable*/ = typename std::enable_if<std::is_copy_constructible<T>::value>::type> +constexpr auto enable_if_constructible_helper(std::index_sequence<I...>) noexcept + -> typename std::add_pointer<decltype(T{ ubiq_lref_constructor{I}... })>::type; + +template <class T, std::size_t... I, class /*Enable*/ = typename std::enable_if<!std::is_copy_constructible<T>::value>::type> +constexpr auto enable_if_constructible_helper(std::index_sequence<I...>) noexcept + -> typename std::add_pointer<decltype(T{ ubiq_rref_constructor{I}... })>::type; + +template <class T, std::size_t N, class /*Enable*/ = decltype( enable_if_constructible_helper<T>(detail::make_index_sequence<N>()) ) > +using enable_if_constructible_helper_t = std::size_t; + +///////////////////// Helpers for range size detection +template <std::size_t Begin, std::size_t Last> +using is_one_element_range = std::integral_constant<bool, Begin == Last>; + +using multi_element_range = std::false_type; +using one_element_range = std::true_type; + +///////////////////// Non greedy fields count search. Templates instantiation depth is log(sizeof(T)), templates instantiation count is log(sizeof(T)). +template <class T, std::size_t Begin, std::size_t Middle> +constexpr std::size_t detect_fields_count(detail::one_element_range, long) noexcept { + static_assert( + Begin == Middle, + "====================> Boost.PFR: Internal logic error." + ); + return Begin; +} + +template <class T, std::size_t Begin, std::size_t Middle> +constexpr std::size_t detect_fields_count(detail::multi_element_range, int) noexcept; + +template <class T, std::size_t Begin, std::size_t Middle> +constexpr auto detect_fields_count(detail::multi_element_range, long) noexcept + -> detail::enable_if_constructible_helper_t<T, Middle> +{ + constexpr std::size_t next_v = Middle + (Middle - Begin + 1) / 2; + return detail::detect_fields_count<T, Middle, next_v>(detail::is_one_element_range<Middle, next_v>{}, 1L); +} + +template <class T, std::size_t Begin, std::size_t Middle> +constexpr std::size_t detect_fields_count(detail::multi_element_range, int) noexcept { + constexpr std::size_t next_v = Begin + (Middle - Begin) / 2; + return detail::detect_fields_count<T, Begin, next_v>(detail::is_one_element_range<Begin, next_v>{}, 1L); +} + +///////////////////// Greedy search. Templates instantiation depth is log(sizeof(T)), templates instantiation count is log(sizeof(T))*T in worst case. +template <class T, std::size_t N> +constexpr auto detect_fields_count_greedy_remember(long) noexcept + -> detail::enable_if_constructible_helper_t<T, N> +{ + return N; +} + +template <class T, std::size_t N> +constexpr std::size_t detect_fields_count_greedy_remember(int) noexcept { + return 0; +} + +template <class T, std::size_t Begin, std::size_t Last> +constexpr std::size_t detect_fields_count_greedy(detail::one_element_range) noexcept { + static_assert( + Begin == Last, + "====================> Boost.PFR: Internal logic error." + ); + return detail::detect_fields_count_greedy_remember<T, Begin>(1L); +} + +template <class T, std::size_t Begin, std::size_t Last> +constexpr std::size_t detect_fields_count_greedy(detail::multi_element_range) noexcept { + constexpr std::size_t middle = Begin + (Last - Begin) / 2; + constexpr std::size_t fields_count_big_range = detail::detect_fields_count_greedy<T, middle + 1, Last>( + detail::is_one_element_range<middle + 1, Last>{} + ); + + constexpr std::size_t small_range_begin = (fields_count_big_range ? 0 : Begin); + constexpr std::size_t small_range_last = (fields_count_big_range ? 0 : middle); + constexpr std::size_t fields_count_small_range = detail::detect_fields_count_greedy<T, small_range_begin, small_range_last>( + detail::is_one_element_range<small_range_begin, small_range_last>{} + ); + return fields_count_big_range ? fields_count_big_range : fields_count_small_range; +} + +///////////////////// Choosing between array size, greedy and non greedy search. +template <class T, std::size_t N> +constexpr auto detect_fields_count_dispatch(size_t_<N>, long, long) noexcept + -> typename std::enable_if<std::is_array<T>::value, std::size_t>::type +{ + return sizeof(T) / sizeof(typename std::remove_all_extents<T>::type); +} + +template <class T, std::size_t N> +constexpr auto detect_fields_count_dispatch(size_t_<N>, long, int) noexcept + -> decltype(sizeof(T{})) +{ + constexpr std::size_t middle = N / 2 + 1; + return detail::detect_fields_count<T, 0, middle>(detail::multi_element_range{}, 1L); +} + +template <class T, std::size_t N> +constexpr std::size_t detect_fields_count_dispatch(size_t_<N>, int, int) noexcept { + // T is not default aggregate initialzable. It means that at least one of the members is not default constructible, + // so we have to check all the aggregate initializations for T up to N parameters and return the bigest succeeded + // (we can not use binary search for detecting fields count). + return detail::detect_fields_count_greedy<T, 0, N>(detail::multi_element_range{}); +} + +///////////////////// Returns fields count +template <class T> +constexpr std::size_t fields_count() noexcept { + using type = std::remove_cv_t<T>; + + static_assert( + !std::is_reference<type>::value, + "====================> Boost.PFR: Attempt to get fields count on a reference. This is not allowed because that could hide an issue and different library users expect different behavior in that case." + ); + +#if !PFR_HAS_GUARANTEED_COPY_ELISION + static_assert( + std::is_copy_constructible<std::remove_all_extents_t<type>>::value || ( + std::is_move_constructible<std::remove_all_extents_t<type>>::value + && std::is_move_assignable<std::remove_all_extents_t<type>>::value + ), + "====================> Boost.PFR: Type and each field in the type must be copy constructible (or move constructible and move assignable)." + ); +#endif // #if !PFR_HAS_GUARANTEED_COPY_ELISION + + static_assert( + !std::is_polymorphic<type>::value, + "====================> Boost.PFR: Type must have no virtual function, because otherwise it is not aggregate initializable." + ); + +#ifdef __cpp_lib_is_aggregate + static_assert( + std::is_aggregate<type>::value // Does not return `true` for built-in types. + || std::is_scalar<type>::value, + "====================> Boost.PFR: Type must be aggregate initializable." + ); +#endif + +// Can't use the following. See the non_std_layout.cpp test. +//#if !PFR_USE_CPP17 +// static_assert( +// std::is_standard_layout<type>::value, // Does not return `true` for structs that have non standard layout members. +// "Type must be aggregate initializable." +// ); +//#endif + +#if defined(_MSC_VER) && (_MSC_VER <= 1920) + // Workaround for msvc compilers. Versions <= 1920 have a limit of max 1024 elements in template parameter pack + constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT >= 1024 ? 1024 : sizeof(type) * CHAR_BIT); +#else + constexpr std::size_t max_fields_count = (sizeof(type) * CHAR_BIT); // We multiply by CHAR_BIT because the type may have bitfields in T +#endif + + constexpr std::size_t result = detail::detect_fields_count_dispatch<type>(size_t_<max_fields_count>{}, 1L, 1L); + + detail::assert_first_not_base<type>(detail::make_index_sequence<result>{}); + +#ifndef __cpp_lib_is_aggregate + static_assert( + is_aggregate_initializable_n<type, result>::value, + "====================> Boost.PFR: Types with user specified constructors (non-aggregate initializable types) are not supported." + ); +#endif + + static_assert( + result != 0 || std::is_empty<type>::value || std::is_fundamental<type>::value || std::is_reference<type>::value, + "====================> 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." + ); + + return result; +} + +}} // namespace pfr::detail + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +#endif // PFR_DETAIL_FIELDS_COUNT_HPP diff --git a/contrib/libs/pfr/include/pfr/detail/make_integer_sequence.hpp b/contrib/libs/pfr/include/pfr/detail/make_integer_sequence.hpp new file mode 100644 index 0000000000..b1af047d2f --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/make_integer_sequence.hpp @@ -0,0 +1,90 @@ +// Copyright (c) 2018 Sergei Fedorov +// Copyright (c) 2019-2021 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) + +#ifndef PFR_DETAIL_MAKE_INTEGER_SEQUENCE_HPP +#define PFR_DETAIL_MAKE_INTEGER_SEQUENCE_HPP +#pragma once + +#include <pfr/detail/config.hpp> + +#include <type_traits> +#include <utility> +#include <cstddef> + +namespace pfr { namespace detail { + +#if PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 0 + +#ifdef __has_builtin +# if __has_builtin(__make_integer_seq) +# define PFR_USE_MAKE_INTEGER_SEQ_BUILTIN +# endif +#endif + +#ifdef PFR_USE_MAKE_INTEGER_SEQ_BUILTIN + +using std::integer_sequence; + +// Clang unable to use namespace qualified std::integer_sequence in __make_integer_seq. +template <typename T, T N> +using make_integer_sequence = __make_integer_seq<integer_sequence, T, N>; + +#undef PFR_USE_MAKE_INTEGER_SEQ_BUILTIN + +#else + +template <typename T, typename U> +struct join_sequences; + +template <typename T, T... A, T... B> +struct join_sequences<std::integer_sequence<T, A...>, std::integer_sequence<T, B...>> { + using type = std::integer_sequence<T, A..., B...>; +}; + +template <typename T, T Min, T Max> +struct build_sequence_impl { + static_assert(Min < Max, "Start of range must be less than its end"); + static constexpr T size = Max - Min; + using type = typename join_sequences< + typename build_sequence_impl<T, Min, Min + size / 2>::type, + typename build_sequence_impl<T, Min + size / 2 + 1, Max>::type + >::type; +}; + +template <typename T, T V> +struct build_sequence_impl<T, V, V> { + using type = std::integer_sequence<T, V>; +}; + +template <typename T, std::size_t N> +struct make_integer_sequence_impl : build_sequence_impl<T, 0, N - 1> {}; + +template <typename T> +struct make_integer_sequence_impl<T, 0> { + using type = std::integer_sequence<T>; +}; + +template <typename T, T N> +using make_integer_sequence = typename make_integer_sequence_impl<T, N>::type; + +#endif // !defined PFR_USE_MAKE_INTEGER_SEQ_BUILTIN +#else // PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 1 + +template <typename T, T N> +using make_integer_sequence = std::make_integer_sequence<T, N>; + +#endif // PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == 1 + +template <std::size_t N> +using make_index_sequence = make_integer_sequence<std::size_t, N>; + +template <typename... T> +using index_sequence_for = make_index_sequence<sizeof...(T)>; + +}} // namespace pfr::detail + +#endif + diff --git a/contrib/libs/pfr/include/pfr/detail/sequence_tuple.hpp b/contrib/libs/pfr/include/pfr/detail/sequence_tuple.hpp new file mode 100644 index 0000000000..3ccd130914 --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/sequence_tuple.hpp @@ -0,0 +1,127 @@ +// Copyright (c) 2016-2021 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) + +#ifndef PFR_DETAIL_SEQUENCE_TUPLE_HPP +#define PFR_DETAIL_SEQUENCE_TUPLE_HPP +#pragma once + +#include <pfr/detail/config.hpp> +#include <pfr/detail/make_integer_sequence.hpp> + +#include <utility> // metaprogramming stuff +#include <cstddef> // std::size_t + +///////////////////// Tuple that holds its values in the supplied order +namespace pfr { namespace detail { namespace sequence_tuple { + +template <std::size_t N, class T> +struct base_from_member { + T value; +}; + +template <class I, class ...Tail> +struct tuple_base; + + + +template <std::size_t... I, class ...Tail> +struct tuple_base< std::index_sequence<I...>, Tail... > + : base_from_member<I , Tail>... +{ + static constexpr std::size_t size_v = sizeof...(I); + + // We do not use `noexcept` in the following functions, because if user forget to put one then clang will issue an error: + // "error: exception specification of explicitly defaulted default constructor does not match the calculated one". + constexpr tuple_base() = default; + constexpr tuple_base(tuple_base&&) = default; + constexpr tuple_base(const tuple_base&) = default; + + constexpr tuple_base(Tail... v) noexcept + : base_from_member<I, Tail>{ v }... + {} +}; + +template <> +struct tuple_base<std::index_sequence<> > { + static constexpr std::size_t size_v = 0; +}; + +template <std::size_t N, class T> +constexpr T& get_impl(base_from_member<N, T>& t) noexcept { + return t.value; +} + +template <std::size_t N, class T> +constexpr const T& get_impl(const base_from_member<N, T>& t) noexcept { + return t.value; +} + +template <std::size_t N, class T> +constexpr volatile T& get_impl(volatile base_from_member<N, T>& t) noexcept { + return t.value; +} + +template <std::size_t N, class T> +constexpr const volatile T& get_impl(const volatile base_from_member<N, T>& t) noexcept { + return t.value; +} + +template <std::size_t N, class T> +constexpr T&& get_impl(base_from_member<N, T>&& t) noexcept { + return std::forward<T>(t.value); +} + + +template <class ...Values> +struct tuple: tuple_base< + detail::index_sequence_for<Values...>, + Values...> +{ + using tuple_base< + detail::index_sequence_for<Values...>, + Values... + >::tuple_base; +}; + + +template <std::size_t N, class ...T> +constexpr decltype(auto) get(tuple<T...>& t) noexcept { + static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds"); + return sequence_tuple::get_impl<N>(t); +} + +template <std::size_t N, class ...T> +constexpr decltype(auto) get(const tuple<T...>& t) noexcept { + static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds"); + return sequence_tuple::get_impl<N>(t); +} + +template <std::size_t N, class ...T> +constexpr decltype(auto) get(const volatile tuple<T...>& t) noexcept { + static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds"); + return sequence_tuple::get_impl<N>(t); +} + +template <std::size_t N, class ...T> +constexpr decltype(auto) get(volatile tuple<T...>& t) noexcept { + static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds"); + return sequence_tuple::get_impl<N>(t); +} + +template <std::size_t N, class ...T> +constexpr decltype(auto) get(tuple<T...>&& t) noexcept { + static_assert(N < tuple<T...>::size_v, "====================> Boost.PFR: Tuple index out of bounds"); + return sequence_tuple::get_impl<N>(std::move(t)); +} + +template <std::size_t I, class T> +using tuple_element = std::remove_reference< decltype( + ::pfr::detail::sequence_tuple::get<I>( std::declval<T>() ) + ) >; + + +}}} // namespace pfr::detail::sequence_tuple + +#endif // PFR_CORE_HPP diff --git a/contrib/libs/pfr/include/pfr/detail/size_t_.hpp b/contrib/libs/pfr/include/pfr/detail/size_t_.hpp new file mode 100644 index 0000000000..da54096b0e --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/size_t_.hpp @@ -0,0 +1,18 @@ +// Copyright (c) 2016-2021 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) + +#ifndef PFR_DETAIL_SIZE_T_HPP +#define PFR_DETAIL_SIZE_T_HPP +#pragma once + +namespace pfr { namespace detail { + +///////////////////// General utility stuff +template <std::size_t Index> +using size_t_ = std::integral_constant<std::size_t, Index >; + +}} // namespace pfr::detail + +#endif // PFR_DETAIL_SIZE_T_HPP diff --git a/contrib/libs/pfr/include/pfr/detail/unsafe_declval.hpp b/contrib/libs/pfr/include/pfr/detail/unsafe_declval.hpp new file mode 100644 index 0000000000..3742abcd2a --- /dev/null +++ b/contrib/libs/pfr/include/pfr/detail/unsafe_declval.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2019-2021 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) + +#ifndef PFR_DETAIL_UNSAFE_DECLVAL_HPP +#define PFR_DETAIL_UNSAFE_DECLVAL_HPP + +#include <pfr/detail/config.hpp> + +#include <type_traits> + +namespace pfr { namespace detail { + +// This function serves as a link-time assert. If linker requires it, then +// `unsafe_declval()` is used at runtime. +void report_if_you_see_link_error_with_this_function() noexcept; + +// For returning non default constructible types. Do NOT use at runtime! +// +// GCCs std::declval may not be used in potentionally evaluated contexts, +// so we reinvent it. +template <class T> +constexpr T unsafe_declval() noexcept { + report_if_you_see_link_error_with_this_function(); + + typename std::remove_reference<T>::type* ptr = 0; + ptr += 42; // suppresses 'null pointer dereference' warnings + return static_cast<T>(*ptr); +} + +}} // namespace pfr::detail + + +#endif // PFR_DETAIL_UNSAFE_DECLVAL_HPP + diff --git a/contrib/libs/pfr/include/pfr/tuple_size.hpp b/contrib/libs/pfr/include/pfr/tuple_size.hpp new file mode 100644 index 0000000000..7ad8f08993 --- /dev/null +++ b/contrib/libs/pfr/include/pfr/tuple_size.hpp @@ -0,0 +1,48 @@ +// Copyright (c) 2016-2021 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) + + +#ifndef PFR_TUPLE_SIZE_HPP +#define PFR_TUPLE_SIZE_HPP +#pragma once + +#include <pfr/detail/config.hpp> + +#include <type_traits> +#include <utility> // metaprogramming stuff + +#include <pfr/detail/sequence_tuple.hpp> +#include <pfr/detail/fields_count.hpp> + +/// \file pfr/tuple_size.hpp +/// Contains tuple-like interfaces to get fields count \forcedlink{tuple_size}, \forcedlink{tuple_size_v}. +/// +/// \b Synopsis: +namespace pfr { + +/// Has a static const member variable `value` that contains fields count in a T. +/// Works for any T that supports aggregate initialization. +/// +/// \b Example: +/// \code +/// std::array<int, pfr::tuple_size<my_structure>::value > a; +/// \endcode +template <class T> +using tuple_size = detail::size_t_< pfr::detail::fields_count<T>() >; + + +/// `tuple_size_v` is a template variable that contains fields count in a T and +/// works for any T that supports aggregate initialization. +/// +/// \b Example: +/// \code +/// std::array<int, pfr::tuple_size_v<my_structure> > a; +/// \endcode +template <class T> +constexpr std::size_t tuple_size_v = tuple_size<T>::value; + +} // namespace pfr + +#endif // PFR_TUPLE_SIZE_HPP diff --git a/contrib/libs/pfr/ya.make b/contrib/libs/pfr/ya.make new file mode 100644 index 0000000000..cdf2bfde6c --- /dev/null +++ b/contrib/libs/pfr/ya.make @@ -0,0 +1,20 @@ +# Generated by devtools/yamaker from nixpkgs 22.05. + +LIBRARY() + +LICENSE( + BSL-1.0 AND + Public-Domain +) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +VERSION(2.0.3) + +ORIGINAL_SOURCE(https://github.com/apolukhin/pfr_non_boost/archive/2.0.3.tar.gz) + +ADDINCL( + GLOBAL contrib/libs/pfr/include +) + +END() |