mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
More static asserts and tests on unions (#22)
This commit is contained in:
@@ -547,6 +547,10 @@ constexpr bool is_flat_refelectable(std::index_sequence<I...>) noexcept {
|
||||
|
||||
template <class T>
|
||||
auto tie_as_flat_tuple(T& lvalue) noexcept {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to flat_ reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
using type = std::remove_cv_t<T>;
|
||||
using tuple_type = internal_tuple_with_same_alignment_t<type>;
|
||||
|
||||
@@ -558,9 +562,12 @@ auto tie_as_flat_tuple(T& lvalue) noexcept {
|
||||
|
||||
template <class T>
|
||||
auto tie_as_tuple(T& val) noexcept {
|
||||
typedef T type;
|
||||
static_assert(
|
||||
boost::pfr::detail::is_flat_refelectable<type>( std::make_index_sequence<fields_count<type>()>{} ),
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
static_assert(
|
||||
boost::pfr::detail::is_flat_refelectable<T>( std::make_index_sequence<boost::pfr::detail::fields_count<T>()>{} ),
|
||||
"Not possible in C++14 to represent that type without loosing information. Use boost::pfr::flat_ version, or change type definition, or enable C++17"
|
||||
);
|
||||
return boost::pfr::detail::tie_as_flat_tuple(val);
|
||||
@@ -662,6 +669,11 @@ void for_each_field_dispatcher_1(T& t, F&& f, std::index_sequence<I...>, std::fa
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
|
||||
/// Compile time error at this point means that you have called `for_each_field` or some other non-flat function or operator for a
|
||||
/// type that is not constexpr aggregate initializable.
|
||||
///
|
||||
|
||||
@@ -139,7 +139,16 @@ decltype(auto) tie_or_value(T& val, std::enable_if_t<std::is_enum<std::remove_re
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) tie_or_value(T& val, std::enable_if_t<!std::is_class< std::remove_reference_t<T> >::value && !std::is_enum< std::remove_reference_t<T> >::value>* = 0) noexcept {
|
||||
auto tie_or_value(T& val, std::enable_if_t<std::is_union< std::remove_reference_t<T> >::value>* = 0) noexcept {
|
||||
static_assert(
|
||||
sizeof(T) && false,
|
||||
"For safety reasons it is forbidden to flat_ reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
decltype(auto) tie_or_value(T& val, std::enable_if_t<!std::is_class< std::remove_reference_t<T> >::value && !std::is_enum< std::remove_reference_t<T> >::value && !std::is_union< std::remove_reference_t<T> >::value>* = 0) noexcept {
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -166,6 +175,10 @@ auto tie_as_tuple_recursively(rvalue_t<T> tup) noexcept {
|
||||
|
||||
template <class T>
|
||||
auto tie_as_flat_tuple(T& t) {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to flat_ reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
auto rec_tuples = boost::pfr::detail::tie_as_tuple_recursively(
|
||||
boost::pfr::detail::tie_as_tuple_loophole_impl(t)
|
||||
);
|
||||
@@ -179,6 +192,10 @@ auto tie_as_flat_tuple(T& t) {
|
||||
#if !BOOST_PFR_USE_CPP17
|
||||
template <class T>
|
||||
auto tie_as_tuple(T& val) noexcept {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
return boost::pfr::detail::tie_as_tuple_loophole_impl(
|
||||
val
|
||||
);
|
||||
@@ -186,6 +203,10 @@ auto tie_as_tuple(T& val) noexcept {
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
std::forward<F>(f)(
|
||||
boost::pfr::detail::tie_as_tuple_loophole_impl(t)
|
||||
);
|
||||
|
||||
@@ -48,6 +48,10 @@ static_assert(
|
||||
|
||||
template <class T, class F, std::size_t... I>
|
||||
void for_each_field_dispatcher(T& t, F&& f, std::index_sequence<I...>) {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
std::forward<F>(f)(
|
||||
detail::tie_as_tuple(t)
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2016-2017 Antony Polukhin
|
||||
// Copyright (c) 2016-2018 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)
|
||||
@@ -1028,6 +1028,10 @@ constexpr auto tie_as_tuple(T& val, size_t_<100>) noexcept {
|
||||
|
||||
template <class T>
|
||||
constexpr auto tie_as_tuple(T& val) noexcept {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
typedef size_t_<fields_count<T>()> fields_count_tag;
|
||||
return boost::pfr::detail::tie_as_tuple(val, fields_count_tag{});
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import string
|
||||
# Skipping some letters that may produce keywords or are hard to read, or shadow template parameters
|
||||
ascii_letters = string.ascii_letters.replace("o", "").replace("O", "").replace("i", "").replace("I", "").replace("T", "")
|
||||
|
||||
PROLOGUE = """// Copyright (c) 2016-2017 Antony Polukhin
|
||||
PROLOGUE = """// Copyright (c) 2016-2018 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)
|
||||
@@ -68,6 +68,10 @@ EPILOGUE = """
|
||||
|
||||
template <class T>
|
||||
constexpr auto tie_as_tuple(T& val) noexcept {
|
||||
static_assert(
|
||||
!std::is_union<T>::value,
|
||||
"For safety reasons it is forbidden to reflect unions. It could lead to crashes (for example when attempting to output the union with inactive first `const char*` field)."
|
||||
);
|
||||
typedef size_t_<fields_count<T>()> fields_count_tag;
|
||||
return boost::pfr::detail::tie_as_tuple(val, fields_count_tag{});
|
||||
}
|
||||
|
||||
@@ -62,6 +62,11 @@ test-suite pfr
|
||||
[ compile-fail common/virtual_functions.cpp : $(CLASSIC_PREC_DEF) : precise_virtual_functions ]
|
||||
[ compile-fail common/virtual_functions.cpp : $(LOOPHOLE_PREC_DEF) : precise_lh_virtual_functions ]
|
||||
|
||||
[ compile-fail common/ops_on_union.cpp : $(CLASSIC_FLAT_DEF) : flat_on_union ]
|
||||
[ compile-fail common/ops_on_union.cpp : $(LOOPHOLE_FLAT_DEF) : flat_lh_on_union ]
|
||||
[ compile-fail common/ops_on_union.cpp : $(CLASSIC_PREC_DEF) : precise_on_union ]
|
||||
[ compile-fail common/ops_on_union.cpp : $(LOOPHOLE_PREC_DEF) : precise_lh_on_union ]
|
||||
|
||||
[ compile-fail common/ops_unions.cpp : $(CLASSIC_FLAT_DEF) : flat_unions ]
|
||||
[ compile-fail common/ops_unions.cpp : $(LOOPHOLE_FLAT_DEF) : flat_lh_unions ]
|
||||
[ compile-fail common/ops_unions.cpp : $(CLASSIC_PREC_DEF) : precise_unions ]
|
||||
|
||||
26
test/common/ops_on_union.cpp
Normal file
26
test/common/ops_on_union.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2018 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)
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef BOOST_PFR_TEST_FLAT
|
||||
#include <boost/pfr/flat/ops.hpp>
|
||||
using namespace boost::pfr::flat_ops;
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_PFR_TEST_PRECISE
|
||||
#include <boost/pfr/precise/ops.hpp>
|
||||
using namespace boost::pfr::ops;
|
||||
#endif
|
||||
|
||||
union test_union {
|
||||
const char* c;
|
||||
int i;
|
||||
};
|
||||
|
||||
int main() {
|
||||
test_union v{""};
|
||||
return v == v;
|
||||
}
|
||||
Reference in New Issue
Block a user