Skip to content

Instantly share code, notes, and snippets.

@Ostoic
Created July 16, 2018 11:28
Show Gist options
  • Save Ostoic/a5772d46b05114ffd9998a9b2c32f164 to your computer and use it in GitHub Desktop.
Save Ostoic/a5772d46b05114ffd9998a9b2c32f164 to your computer and use it in GitHub Desktop.
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