mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
Operators and functors for precise mode added
This commit is contained in:
36
include/boost/pfr/detail/detectors.hpp
Normal file
36
include/boost/pfr/detail/detectors.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2016 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 BOOST_PFR_DETAIL_DETECTORS_HPP
|
||||
#define BOOST_PFR_DETAIL_DETECTORS_HPP
|
||||
|
||||
namespace boost { namespace pfr { namespace detail {
|
||||
///////////////////// `value` is true if Detector<Tleft, Tright> does not compile (SFINAE)
|
||||
template <template <class, class> class Detector, class Tleft, class Tright>
|
||||
struct not_appliable {
|
||||
struct success{};
|
||||
template <class Tl, class Tr> static Detector<Tl, Tr> detector_impl(long) noexcept;
|
||||
template <class Tl, class Tr> static success detector_impl(int) noexcept;
|
||||
|
||||
static constexpr bool value = std::is_same<
|
||||
decltype(detector_impl<Tleft, Tright>(1L)),
|
||||
success
|
||||
>::value;
|
||||
};
|
||||
|
||||
///////////////////// Detectors for different operators
|
||||
template <class T1, class T2> using comp_eq_detector = decltype(std::declval<T1>() == std::declval<T2>());
|
||||
template <class T1, class T2> using comp_ne_detector = decltype(std::declval<T1>() != std::declval<T2>());
|
||||
template <class T1, class T2> using comp_lt_detector = decltype(std::declval<T1>() < std::declval<T2>());
|
||||
template <class T1, class T2> using comp_le_detector = decltype(std::declval<T1>() <= std::declval<T2>());
|
||||
template <class T1, class T2> using comp_gt_detector = decltype(std::declval<T1>() > std::declval<T2>());
|
||||
template <class T1, class T2> using comp_ge_detector = decltype(std::declval<T1>() >= std::declval<T2>());
|
||||
template <class S, class T> using ostreamable_detector = decltype(std::declval<S>() << std::declval<T>());
|
||||
template <class S, class T> using istreamable_detector = decltype(std::declval<S>() >> std::declval<T>());
|
||||
|
||||
}}} // namespace boost::pfr::detail
|
||||
|
||||
#endif // BOOST_PFR_DETAIL_DETECTORS_HPP
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
// 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)
|
||||
|
||||
#pragma once
|
||||
#ifndef BOOST_PFR_FLAT_OPS_HPP
|
||||
#define BOOST_PFR_FLAT_OPS_HPP
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
# error C++14 is required for this header.
|
||||
#endif
|
||||
|
||||
#include <boost/pfr/detail/detectors.hpp>
|
||||
#include <boost/pfr/flat/functors.hpp>
|
||||
|
||||
/// \file boost/pfr/flat/ops.hpp
|
||||
@@ -39,53 +41,31 @@
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
namespace detail {
|
||||
///////////////////// `value` is true if Detector<Tleft, Tright> does not compile (SFINAE)
|
||||
template <template <class, class> class Detector, class Tleft, class Tright>
|
||||
struct not_appliable {
|
||||
struct success{};
|
||||
template <class Tl, class Tr> static Detector<Tl, Tr> detector_impl(long) noexcept;
|
||||
template <class Tl, class Tr> static success detector_impl(int) noexcept;
|
||||
|
||||
static constexpr bool value = std::is_same<
|
||||
decltype(detector_impl<Tleft, Tright>(1L)),
|
||||
success
|
||||
>::value;
|
||||
};
|
||||
|
||||
///////////////////// Detectors for different operators
|
||||
template <class T1, class T2> using comp_eq_detector = decltype(std::declval<T1>() == std::declval<T2>());
|
||||
template <class T1, class T2> using comp_ne_detector = decltype(std::declval<T1>() != std::declval<T2>());
|
||||
template <class T1, class T2> using comp_lt_detector = decltype(std::declval<T1>() < std::declval<T2>());
|
||||
template <class T1, class T2> using comp_le_detector = decltype(std::declval<T1>() <= std::declval<T2>());
|
||||
template <class T1, class T2> using comp_gt_detector = decltype(std::declval<T1>() > std::declval<T2>());
|
||||
template <class T1, class T2> using comp_ge_detector = decltype(std::declval<T1>() >= std::declval<T2>());
|
||||
template <class S, class T> using ostreamable_detector = decltype(std::declval<S>() << std::declval<T>());
|
||||
template <class S, class T> using istreamable_detector = decltype(std::declval<S>() >> std::declval<T>());
|
||||
|
||||
///////////////////// Helper typedef that it used by all the enable_not_*_comp_t
|
||||
///////////////////// Helper typedef that it used by all the enable_flat_not_*_comp_t
|
||||
template <template <class, class> class Detector, class T>
|
||||
using enable_not_comp_base_t = typename std::enable_if<
|
||||
using enable_flat_not_comp_base_t = typename std::enable_if<
|
||||
not_appliable<Detector, T const&, T const&>::value && std::is_pod<T>::value,
|
||||
bool
|
||||
>::type;
|
||||
|
||||
///////////////////// std::enable_if_t like functions that enable only if types do not support operation and are PODs
|
||||
|
||||
template <class T> using enable_not_eq_comp_t = enable_not_comp_base_t<comp_eq_detector, T>;
|
||||
template <class T> using enable_not_ne_comp_t = enable_not_comp_base_t<comp_ne_detector, T>;
|
||||
template <class T> using enable_not_lt_comp_t = enable_not_comp_base_t<comp_lt_detector, T>;
|
||||
template <class T> using enable_not_le_comp_t = enable_not_comp_base_t<comp_le_detector, T>;
|
||||
template <class T> using enable_not_gt_comp_t = enable_not_comp_base_t<comp_gt_detector, T>;
|
||||
template <class T> using enable_not_ge_comp_t = enable_not_comp_base_t<comp_ge_detector, T>;
|
||||
template <class T> using enable_flat_not_eq_comp_t = enable_flat_not_comp_base_t<comp_eq_detector, T>;
|
||||
template <class T> using enable_flat_not_ne_comp_t = enable_flat_not_comp_base_t<comp_ne_detector, T>;
|
||||
template <class T> using enable_flat_not_lt_comp_t = enable_flat_not_comp_base_t<comp_lt_detector, T>;
|
||||
template <class T> using enable_flat_not_le_comp_t = enable_flat_not_comp_base_t<comp_le_detector, T>;
|
||||
template <class T> using enable_flat_not_gt_comp_t = enable_flat_not_comp_base_t<comp_gt_detector, T>;
|
||||
template <class T> using enable_flat_not_ge_comp_t = enable_flat_not_comp_base_t<comp_ge_detector, T>;
|
||||
|
||||
template <class Stream, class Type>
|
||||
using enable_not_ostreamable_t = typename std::enable_if<
|
||||
using enable_flat_not_ostreamable_t = typename std::enable_if<
|
||||
not_appliable<ostreamable_detector, Stream&, Type const&>::value && std::is_pod<Type>::value,
|
||||
Stream&
|
||||
>::type;
|
||||
|
||||
template <class Stream, class Type>
|
||||
using enable_not_istreamable_t = typename std::enable_if<
|
||||
using enable_flat_not_istreamable_t = typename std::enable_if<
|
||||
not_appliable<istreamable_detector, Stream&, Type&>::value && std::is_pod<Type>::value,
|
||||
Stream&
|
||||
>::type;
|
||||
@@ -110,44 +90,44 @@ namespace flat_ops {
|
||||
template <class T> std::size_t hash_value(const T& value) noexcept;
|
||||
#else
|
||||
template <class T>
|
||||
static detail::enable_not_eq_comp_t<T> operator==(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_eq_comp_t<T> operator==(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_equal_to<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_ne_comp_t<T> operator!=(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_ne_comp_t<T> operator!=(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_not_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_lt_comp_t<T> operator<(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_lt_comp_t<T> operator<(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_less<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_gt_comp_t<T> operator>(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_gt_comp_t<T> operator>(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_greater<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_le_comp_t<T> operator<=(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_le_comp_t<T> operator<=(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_less_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_ge_comp_t<T> operator>=(const T& lhs, const T& rhs) noexcept {
|
||||
static detail::enable_flat_not_ge_comp_t<T> operator>=(const T& lhs, const T& rhs) noexcept {
|
||||
return flat_greater_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
static detail::enable_not_ostreamable_t<std::basic_ostream<Char, Traits>, T> operator<<(std::basic_ostream<Char, Traits>& out, const T& value) {
|
||||
flat_write(out, value);
|
||||
static detail::enable_flat_not_ostreamable_t<std::basic_ostream<Char, Traits>, T> operator<<(std::basic_ostream<Char, Traits>& out, const T& value) {
|
||||
boost::pfr::flat_write(out, value);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
static detail::enable_not_istreamable_t<std::basic_istream<Char, Traits>, T> operator>>(std::basic_istream<Char, Traits>& in, T& value) {
|
||||
flat_read(in, value);
|
||||
static detail::enable_flat_not_istreamable_t<std::basic_istream<Char, Traits>, T> operator>>(std::basic_istream<Char, Traits>& in, T& value) {
|
||||
boost::pfr::flat_read(in, value);
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -160,3 +140,5 @@ namespace flat_ops {
|
||||
} // namespace flat_ops
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_FLAT_OPS_HPP
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
/// Includes all the Boost.PFR headers that do not define `flat_*` functions, except \xmlonly<link linkend='header.boost.pfr.precise.global_ops_hpp'>boost/pfr/precise/global_ops.hpp</link>\endxmlonly
|
||||
|
||||
#include <boost/pfr/precise/core.hpp>
|
||||
#include <boost/pfr/precise/functors.hpp>
|
||||
#include <boost/pfr/precise/ops.hpp>
|
||||
|
||||
#endif // BOOST_PFR_PRECISE_HPP
|
||||
|
||||
239
include/boost/pfr/precise/functors.hpp
Normal file
239
include/boost/pfr/precise/functors.hpp
Normal file
@@ -0,0 +1,239 @@
|
||||
// Copyright (c) 2016 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 BOOST_PFR_PRECISE_FUNCTORS_HPP
|
||||
#define BOOST_PFR_PRECISE_FUNCTORS_HPP
|
||||
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
# error C++14 is required for this header.
|
||||
#endif
|
||||
|
||||
#include <boost/pfr/detail/functional.hpp>
|
||||
#include <boost/pfr/flat/core.hpp>
|
||||
|
||||
/// \file boost/pfr/functors.hpp
|
||||
/// Contains functors that are close to the Standard Library ones.
|
||||
/// Each functor iterates over fields of the type.
|
||||
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <template <std::size_t, std::size_t> class Visitor, class T, class U>
|
||||
bool binary_visit(const T& x, const U& y) {
|
||||
constexpr std::size_t fields_count_lhs = detail::fields_count<std::remove_reference_t<T>>();
|
||||
constexpr std::size_t fields_count_rhs = detail::fields_count<std::remove_reference_t<U>>();
|
||||
constexpr std::size_t fields_count_min = detail::min_size(fields_count_lhs, fields_count_rhs);
|
||||
typedef Visitor<0, fields_count_min> visitor_t;
|
||||
|
||||
#if __cplusplus >= 201606L /* Oulu meeting, not the exact value */
|
||||
return visitor_t::cmp(detail::as_tuple(x), detail::as_tuple(y));
|
||||
#else
|
||||
bool result = true;
|
||||
::boost::pfr::detail::for_each_field_dispatcher(
|
||||
x,
|
||||
[&result, &y](const auto& lhs) {
|
||||
::boost::pfr::detail::for_each_field_dispatcher(
|
||||
y,
|
||||
[&result, &lhs](const auto& rhs) {
|
||||
result = visitor_t::cmp(lhs, rhs);
|
||||
},
|
||||
std::make_index_sequence<fields_count_rhs>{}
|
||||
);
|
||||
},
|
||||
std::make_index_sequence<fields_count_lhs>{}
|
||||
);
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
///////////////////// Comparisons
|
||||
|
||||
/// \brief std::equal_to like comparator
|
||||
template <class T = void> struct equal_to {
|
||||
/// \return \b true if each field of \b x equals the field with same index of \b y
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::equal_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct equal_to<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::equal_impl>(x, y);
|
||||
}
|
||||
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// \brief std::not_equal like comparator
|
||||
template <class T = void> struct not_equal {
|
||||
/// \return \b true if at least one field \b x not equals the field with same index of \b y
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::not_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct not_equal<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::not_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
typedef std::true_type is_transparent;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// \brief std::greater like comparator
|
||||
template <class T = void> struct greater {
|
||||
/// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x eqeal to the same fields of \b y
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::greater_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct greater<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::greater_impl>(x, y);
|
||||
}
|
||||
|
||||
typedef std::true_type is_transparent;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// \brief std::less like comparator
|
||||
template <class T = void> struct less {
|
||||
/// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x eqeal to the same fields of \b y
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::less_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct less<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::less_impl>(x, y);
|
||||
}
|
||||
|
||||
typedef std::true_type is_transparent;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// \brief std::greater_equal like comparator
|
||||
template <class T = void> struct greater_equal {
|
||||
/// \return \b true if field of \b x greater than the field with same index of \b y and all previous fields of \b x eqeal to the same fields of \b y;
|
||||
/// or if each field of \b x equals the field with same index of \b y .
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::greater_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct greater_equal<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::greater_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
typedef std::true_type is_transparent;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// \brief std::less_equal like comparator
|
||||
template <class T = void> struct less_equal {
|
||||
/// \return \b true if field of \b x less than the field with same index of \b y and all previous fields of \b x eqeal to the same fields of \b y;
|
||||
/// or if each field of \b x equals the field with same index of \b y .
|
||||
bool operator()(const T& x, const T& y) const {
|
||||
return detail::binary_visit<detail::less_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
/// This typedef exists only if T \b is void
|
||||
typedef std::true_type is_transparent;
|
||||
|
||||
/// This operator allows comparison of \b x and \b y that have different type.
|
||||
/// \pre Exists only if T \b is void.
|
||||
template <class V, class U> bool operator()(const V& x, const U& y) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <> struct less_equal<void> {
|
||||
template <class T, class U>
|
||||
bool operator()(const T& x, const U& y) const {
|
||||
return detail::binary_visit<detail::less_equal_impl>(x, y);
|
||||
}
|
||||
|
||||
typedef std::true_type is_transparent;
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
|
||||
/// \brief std::hash like functor
|
||||
template <class T> struct hash {
|
||||
/// \return hash value of \b x
|
||||
std::size_t operator()(const T& x) const noexcept {
|
||||
return detail::hash_impl<0, detail::fields_count<std::remove_reference_t<T>>() >::compute(detail::as_tuple(x));
|
||||
}
|
||||
};
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_PRECISE_FUNCTORS_HPP
|
||||
145
include/boost/pfr/precise/ops.hpp
Normal file
145
include/boost/pfr/precise/ops.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2016 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 BOOST_PFR_PRECISE_OPS_HPP
|
||||
#define BOOST_PFR_PRECISE_OPS_HPP
|
||||
|
||||
#if __cplusplus < 201402L
|
||||
# error C++14 is required for this header.
|
||||
#endif
|
||||
|
||||
#include <boost/pfr/detail/detectors.hpp>
|
||||
#include <boost/pfr/precise/functors.hpp>
|
||||
#include <boost/pfr/precise/core.hpp>
|
||||
|
||||
/// \file boost/pfr/precise/ops.hpp
|
||||
/// Contains comparison operators and stream operators for types that do not have their own operators.
|
||||
/// If type is comparable or streamable using it's own operator or it's conversion operator, then the original operator is used.
|
||||
///
|
||||
/// Just write \b using \b namespace \b ops; and operators will be available in scope.
|
||||
///
|
||||
/// \b Example:
|
||||
/// \code
|
||||
/// #include <boost/pfr/precise/ops.hpp>
|
||||
/// struct comparable_struct { // No operators defined for that structure
|
||||
/// int i; short s; char data[7]; bool bl; int a,b,c,d,e,f;
|
||||
/// };
|
||||
/// // ...
|
||||
///
|
||||
/// using namespace ops;
|
||||
///
|
||||
/// comparable_struct s1 {0, 1, "Hello", false, 6,7,8,9,10,11};
|
||||
/// comparable_struct s2 {0, 1, "Hello", false, 6,7,8,9,10,11111};
|
||||
/// assert(s1 < s2);
|
||||
/// std::cout << s1 << std::endl; // Outputs: {0, 1, H, e, l, l, o, , , 0, 6, 7, 8, 9, 10, 11}
|
||||
/// \endcode
|
||||
///
|
||||
/// \podops for other ways to define operators and more details.
|
||||
///
|
||||
/// \b This \b header \b contains:
|
||||
namespace boost { namespace pfr {
|
||||
|
||||
namespace detail {
|
||||
|
||||
///////////////////// Helper typedef that it used by all the enable_not_*_comp_t
|
||||
template <template <class, class> class Detector, class T>
|
||||
using enable_not_comp_base_t = typename std::enable_if<
|
||||
not_appliable<Detector, T const&, T const&>::value,
|
||||
bool
|
||||
>::type;
|
||||
|
||||
///////////////////// std::enable_if_t like functions that enable only if types do not support operation and are PODs
|
||||
|
||||
template <class T> using enable_not_eq_comp_t = enable_not_comp_base_t<comp_eq_detector, T>;
|
||||
template <class T> using enable_not_ne_comp_t = enable_not_comp_base_t<comp_ne_detector, T>;
|
||||
template <class T> using enable_not_lt_comp_t = enable_not_comp_base_t<comp_lt_detector, T>;
|
||||
template <class T> using enable_not_le_comp_t = enable_not_comp_base_t<comp_le_detector, T>;
|
||||
template <class T> using enable_not_gt_comp_t = enable_not_comp_base_t<comp_gt_detector, T>;
|
||||
template <class T> using enable_not_ge_comp_t = enable_not_comp_base_t<comp_ge_detector, T>;
|
||||
|
||||
template <class Stream, class Type>
|
||||
using enable_not_ostreamable_t = typename std::enable_if<
|
||||
not_appliable<ostreamable_detector, Stream&, Type const&>::value,
|
||||
Stream&
|
||||
>::type;
|
||||
|
||||
template <class Stream, class Type>
|
||||
using enable_not_istreamable_t = typename std::enable_if<
|
||||
not_appliable<istreamable_detector, Stream&, Type&>::value,
|
||||
Stream&
|
||||
>::type;
|
||||
} // namespace detail
|
||||
|
||||
namespace ops {
|
||||
#ifdef BOOST_PFR_DOXYGEN_INVOKED
|
||||
template <class T> bool operator==(const T& lhs, const T& rhs) noexcept;
|
||||
template <class T> bool operator!=(const T& lhs, const T& rhs) noexcept;
|
||||
template <class T> bool operator< (const T& lhs, const T& rhs) noexcept;
|
||||
template <class T> bool operator> (const T& lhs, const T& rhs) noexcept;
|
||||
template <class T> bool operator<=(const T& lhs, const T& rhs) noexcept;
|
||||
template <class T> bool operator>=(const T& lhs, const T& rhs) noexcept;
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, const T& value);
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& in, T& value);
|
||||
|
||||
/// \brief helper function for Boost
|
||||
template <class T> std::size_t hash_value(const T& value) noexcept;
|
||||
#else
|
||||
template <class T>
|
||||
static detail::enable_not_eq_comp_t<T> operator==(const T& lhs, const T& rhs) noexcept {
|
||||
return equal_to<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_ne_comp_t<T> operator!=(const T& lhs, const T& rhs) noexcept {
|
||||
return not_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_lt_comp_t<T> operator<(const T& lhs, const T& rhs) noexcept {
|
||||
return less<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_gt_comp_t<T> operator>(const T& lhs, const T& rhs) noexcept {
|
||||
return greater<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_le_comp_t<T> operator<=(const T& lhs, const T& rhs) noexcept {
|
||||
return less_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static detail::enable_not_ge_comp_t<T> operator>=(const T& lhs, const T& rhs) noexcept {
|
||||
return greater_equal<T>{}(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
static detail::enable_not_ostreamable_t<std::basic_ostream<Char, Traits>, T> operator<<(std::basic_ostream<Char, Traits>& out, const T& value) {
|
||||
boost::pfr::write(out, value);
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class Char, class Traits, class T>
|
||||
static detail::enable_not_istreamable_t<std::basic_istream<Char, Traits>, T> operator>>(std::basic_istream<Char, Traits>& in, T& value) {
|
||||
boost::pfr::read(in, value);
|
||||
return in;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static std::enable_if_t<std::is_pod<T>::value, std::size_t> hash_value(const T& value) noexcept {
|
||||
return hash<T>{}(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace ops
|
||||
|
||||
}} // namespace boost::pfr
|
||||
|
||||
#endif // BOOST_PFR_PRECISE_OPS_HPP
|
||||
@@ -8,7 +8,7 @@
|
||||
test-suite pfr
|
||||
:
|
||||
[ run common/ops.cpp : : : <define>BOOST_PFR_TEST_FLAT : flat_ops ]
|
||||
#[ run common/ops.cpp : : : <define>BOOST_PFR_TEST_PRECISE : precise_ops ]
|
||||
[ run common/ops.cpp : : : <define>BOOST_PFR_TEST_PRECISE : precise_ops ]
|
||||
[ run common/read_write.cpp : : : <define>BOOST_PFR_TEST_FLAT : flat_read_write ]
|
||||
[ run common/read_write.cpp : : : <define>BOOST_PFR_TEST_PRECISE : precise_read_write ]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user