| // Part of the Crubit project, under the Apache License v2.0 with LLVM | |
| // Exceptions. See /LICENSE for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| #ifndef CRUBIT_SUPPORT_OFFSETOF_H_ | |
| #define CRUBIT_SUPPORT_OFFSETOF_H_ | |
| #include <cstddef> | |
| namespace crubit::details { | |
| // OffsetOfHelper is very similar to `std::type_identity_t`, except that it | |
| // provides a way to wrap `T` in parens without running into an error message | |
| // like: | |
| // error: expected a type | |
| // static_assert(CRUBIT_OFFSET_OF(field, TestStruct) == 0, ""); | |
| // ^ | |
| // note: expanded from macro 'CRUBIT_OFFSET_OF' | |
| // offsetof((T), member) | |
| // ^ | |
| // or (when using `std::type_identity_t` with parens around T): | |
| // error: expected expression | |
| // static_assert(CRUBIT_OFFSET_OF(offset0, BasicStruct) == 0, ""); | |
| // ^ | |
| // note: expanded from macro 'CRUBIT_OFFSET_OF' | |
| // offsetof(std::type_identity_t<(T)>::type, member) | |
| // ^ | |
| // or (when using `std::type_identity_t` with different parens placement): | |
| // error: expected a type | |
| // static_assert(CRUBIT_OFFSET_OF(field, TestStruct) == 0, ""); | |
| // ^ | |
| // note: expanded from macro 'CRUBIT_OFFSET_OF' | |
| // offsetof((crubit::type_identity_t<T>::type), member) | |
| // ^ | |
| // | |
| // The errors are avoided by allowing passing `T` via `void(T)` syntax through | |
| // the single specialization below. | |
| template <typename T> | |
| struct OffsetOfHelper; | |
| template <typename T> | |
| struct OffsetOfHelper<void(T)> { | |
| using Type = T; | |
| }; | |
| } // namespace crubit::details | |
| // CRUBIT_OFFSET_OF is a wrapper around the standard `offsetof` macro [1] that | |
| // adds support for using a type name (i.e. `...`) that contains commas (e.g. | |
| // `ClassTemplateWithTwoTemplateParameters<int, int>`). | |
| // | |
| // CRUBIT_OFFSET_OF doesn't require wrapping the type name in an extra set of | |
| // parens. This aspect is achieved by making CRUBIT_OFFSET_OF a variadic macro | |
| // (i.e. accepting 2 *or more* arguments) and by making `...` the last | |
| // parameter (i.e. using a different order of macro parameters than the standard | |
| // `offsetof`). | |
| // | |
| // See the doc comments of OffsetOfHelper above for an explanation why wrapping | |
| // the type name in an extra parens is not sufficient for the standard | |
| // `offsetof` macro. | |
| // | |
| // [1] https://en.cppreference.com/w/cpp/types/offsetof | |
| #define CRUBIT_OFFSET_OF(member, ...) \ | |
| offsetof(::crubit::details::OffsetOfHelper<void(__VA_ARGS__)>::Type, member) | |
| #endif // CRUBIT_RS_BINDINGS_FROM_CC_SUPPORT_OFFSETOF_H_ |