mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
nearby: snapshot as of cl/296436629
Signed-off-by: Alexey Polyudov <apolyudov@google.com> Change-Id: I2cf5bf225b76f4c1541954651f3a7544a14e0cec
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#ifndef PLATFORM_CONTAINER_OF_H_
|
||||
#define PLATFORM_CONTAINER_OF_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace location::nearby {
|
||||
|
||||
// Similar to offsetof() macro, but implemented in a type-safe way,
|
||||
// OffsetOf(<pointer-to-member>) returns the byte offset of a given data
|
||||
// member in the ClassType.
|
||||
// Behavior is undefined if member is not a direct, non-static data member of
|
||||
// type ClassType.
|
||||
// usage example:
|
||||
// struct S { int x; double y; };
|
||||
// size_t y_offset = OffsetOf(&S::y);
|
||||
// CHECK(y_offset >= sizeof(int));
|
||||
//
|
||||
// the following is not guaranteed to work:
|
||||
// struct S1 { int x; };
|
||||
// struct S2 { double y; };
|
||||
// struct S : public S1, S2 { char t; };
|
||||
// size_t y_offset_bad = OffsetOf(&S::y);
|
||||
// because S::y is not a direct member of S; it is a member by inheritance.
|
||||
// To make sure OffsetOf works with inherited members, it must be called
|
||||
// with explicitly defined template parameters, as follows:
|
||||
// size_t y_offset_ok = OffsetOf<double,S>(&S::y);
|
||||
//
|
||||
// However, the following is guaranteed to work:
|
||||
// struct S1 { int x; };
|
||||
// struct S2 { double y; };
|
||||
// struct S3 { double z; };
|
||||
// struct S : public S1, S2 { S3 s3; char t; };
|
||||
// size_t s3_offset = OffsetOf(&S::s3);
|
||||
|
||||
template <typename ValueType, typename ClassType>
|
||||
constexpr size_t OffsetOf(const ValueType ClassType::*member) {
|
||||
std::aligned_storage_t<sizeof(ClassType), alignof(ClassType)> obj_memory;
|
||||
ClassType* obj = reinterpret_cast<ClassType*>(&obj_memory);
|
||||
return reinterpret_cast<size_t>(&(obj->*member)) -
|
||||
reinterpret_cast<size_t>(obj);
|
||||
}
|
||||
|
||||
// Similar to Linux containerof() macro, this function returns pointer to
|
||||
// the type instance that contains the specified member;
|
||||
// ContainerOf(<pointer to variable instance of type ValueType, which is member
|
||||
// of ClassType>, <pointer-to-ClassType-member>);
|
||||
// usage example:
|
||||
// struct S { int x; double y; } a;
|
||||
// S *b = ContainerOf(&a.y, &S::y);
|
||||
// CHECK(b == &a);
|
||||
template <typename ValueType, typename ClassType>
|
||||
ClassType* ContainerOf(ValueType* ptr, ValueType ClassType::*member) {
|
||||
using BaseValueType = std::remove_volatile_t<ValueType>;
|
||||
return reinterpret_cast<ClassType*>(
|
||||
reinterpret_cast<char*>(const_cast<BaseValueType*>(ptr)) -
|
||||
OffsetOf(member));
|
||||
}
|
||||
|
||||
template <typename ValueType, typename ClassType>
|
||||
const ClassType* ContainerOf(const ValueType* ptr,
|
||||
ValueType ClassType::*member) {
|
||||
using BaseValueType = std::remove_volatile_t<ValueType>;
|
||||
return reinterpret_cast<const ClassType*>(
|
||||
reinterpret_cast<const char*>(const_cast<BaseValueType*>(ptr)) -
|
||||
OffsetOf(member));
|
||||
}
|
||||
|
||||
} // namespace location::nearby
|
||||
|
||||
#endif // PLATFORM_CONTAINER_OF_H_
|
||||
Reference in New Issue
Block a user