Created
July 16, 2018 11:28
-
-
Save Ostoic/a5772d46b05114ffd9998a9b2c32f164 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace detail | |
{ | |
template <std::size_t I, class Tuple> | |
struct aligned_offset_impl | |
{ | |
constexpr std::size_t operator()() const noexcept | |
{ | |
using current_element_t = std::tuple_element_t<I, Tuple>; | |
using previous_element_t = std::tuple_element_t<I - 1, Tuple>; | |
constexpr auto accumulated_offset = aligned_offset_impl<I - 1, Tuple>{}(); | |
// Check if the offset and size of the previous element gives a correct alignment for the current element. | |
constexpr auto alignment_remainder = (accumulated_offset + sizeof(previous_element_t)) % alignof(current_element_t); | |
if (alignment_remainder == 0) | |
return accumulated_offset + sizeof(previous_element_t); | |
// Calculate the distance needed to be meet the alignment requirements of the current element. | |
constexpr auto needed_distance = (alignof(current_element_t) - accumulated_offset) % alignof(current_element_t); | |
// If the distance matches the alignment, just use the alignment itself (mod == 0 gives 0) | |
if (needed_distance % alignof(current_element_t) == 0) | |
return accumulated_offset + alignof(current_element_t); | |
// In the last case add the needed distance to meet the next element's alignment requirements. | |
return accumulated_offset + needed_distance; | |
} | |
}; | |
template <class Tuple> | |
struct aligned_offset_impl<0, Tuple> | |
{ | |
constexpr std::size_t operator()() const noexcept | |
{ | |
return 0; | |
} | |
}; | |
} | |
/// @brief Calculate the aligned offset of an element in the given tuple as if it were put into a structure. | |
/// @tparam N the index of the element in the tuple. | |
/// @tparam Tuple the tuple to consider. | |
/// @return the aligned offset. | |
/// @note The aligned offset of the \a Nth element in \a Tuple depends on the previous \a N - 1 aligned offsets. | |
template <std::size_t N, class Tuple> | |
constexpr std::size_t aligned_offset() noexcept | |
{ | |
return detail::aligned_offset_impl<N, Tuple>{}(); | |
} | |
struct test1 { short a; char b; char* c; short d; char e; }; | |
using test1_tuple = std::tuple<short, char, char*, short, char>; | |
int main() | |
{ | |
std::cout << "aligned_offset = " << aligned_offset<1, test1_tuple>() << '\n'; | |
std::cout << "offsetof = " << offsetof(test1, b) << '\n'; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment