2
0
mirror of https://github.com/boostorg/pfr.git synced 2026-01-19 04:22:13 +00:00

use cast_to_layout_compatible again for enums in core14_loophole

this partially reverts a subtle change to static_cast in
551b36a536

the reason that is wrong is that the static_cast produces a new value,
while we need to produce a reference to the underlying type of the enum
essentially.
This commit is contained in:
Chris Beck
2017-09-28 07:13:55 -07:00
parent 62b972e500
commit 3aba48c9a9
2 changed files with 78 additions and 1 deletions

View File

@@ -0,0 +1,76 @@
// Copyright (c) 2016-2017 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_CAST_TO_LAYOUT_COMPATIBLE_HPP
#define BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP
#pragma once
#include <boost/pfr/detail/config.hpp>
#include <type_traits>
#include <utility> // metaprogramming stuff
namespace boost { namespace pfr { namespace detail {
template <class T, class U>
constexpr void static_assert_layout_compatible() noexcept {
static_assert(
std::alignment_of<T>::value == std::alignment_of<U>::value,
"Alignment check failed, probably your structure has user-defined alignment for the whole structure or for some of the fields."
);
static_assert(sizeof(T) == sizeof(U), "Size check failed, probably your structure has bitfields or user-defined alignment.");
}
/// @cond
#ifdef __GNUC__
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
/// @endcond
template <class To, class From>
MAY_ALIAS const To& cast_to_layout_compatible(const From& val) noexcept {
MAY_ALIAS const To* const t = reinterpret_cast<const To*>( std::addressof(val) );
static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS const volatile To& cast_to_layout_compatible(const volatile From& val) noexcept {
MAY_ALIAS const volatile To* const t = reinterpret_cast<const volatile To*>( std::addressof(val) );
static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS volatile To& cast_to_layout_compatible(volatile From& val) noexcept {
MAY_ALIAS volatile To* const t = reinterpret_cast<volatile To*>( std::addressof(val) );
static_assert_layout_compatible<To, From>();
return *t;
}
template <class To, class From>
MAY_ALIAS To& cast_to_layout_compatible(From& val) noexcept {
MAY_ALIAS To* const t = reinterpret_cast<To*>( std::addressof(val) );
static_assert_layout_compatible<To, From>();
return *t;
}
/*
template <class To, class From>
MAY_ALIAS std::enable_if_t<std::is_rvalue_reference<From&&>::value, To&&> cast_to_layout_compatible(From&& val) noexcept {
MAY_ALIAS To* const t = reinterpret_cast<To*>( std::addressof(val) );
static_assert_layout_compatible<To, From>();
return std::move(*t);
}*/
#undef MAY_ALIAS
}}} // namespace boost::pfr::detail
#endif // BOOST_PFR_DETAIL_CAST_TO_LAYOUT_COMPATIBLE_HPP

View File

@@ -25,6 +25,7 @@
#include <type_traits>
#include <utility>
#include <boost/pfr/detail/cast_to_layout_compatible.hpp> // still needed for enums
#include <boost/pfr/detail/offset_based_getter.hpp>
#include <boost/pfr/detail/fields_count.hpp>
#include <boost/pfr/detail/make_flat_tuple_of_references.hpp>
@@ -123,7 +124,7 @@ auto tie_or_value(T&& val, std::enable_if_t<std::is_class< std::remove_reference
template <class T>
decltype(auto) tie_or_value(T&& val, std::enable_if_t<std::is_enum<std::remove_reference_t<T>>::value>* = 0) noexcept {
return static_cast<
return cast_to_layout_compatible<
std::underlying_type_t<std::remove_reference_t<T> >
>( std::forward<T>(val) );
}