c ++ 11 — смещение времени компиляции C ++ внутри шаблона

У меня есть необходимость использовать offsetof из template с селектором члена. Я придумал способ, если вы простите неловкий синтаксис:

template <typename T,
typename R,
R T::*M
>
constexpr std::size_t offset_of()
{
return reinterpret_cast<std::size_t>(&(((T*)0)->*M));
};

Использование не идеально (раздражает в лучшем случае):

struct S
{
int x;
int y;
};

static_assert(offset_of<S, int, &S::x>() == 0, "");
static_assert(offset_of<S, int, &S::y>() == sizeof(int), "");

Затем на-constexpr Форма проще в использовании:

template <typename T, typename R>
std::size_t offset_of(R T::*M)
{
return reinterpret_cast<std::size_t>(&(((T*)0)->*M));
};

с очевидным недостатком, что это не делается во время компиляции (но проще в использовании):

int main()
{
std::cout << offset_of(&S::x) << std::endl;
std::cout << offset_of(&S::y) << std::endl;
}

То, что я ищу, это синтаксис лайк Затем на-constexpr разнообразие, но все еще полностью компилируемое; однако я не могу придумать синтаксис для этого. Я также был бы счастлив с offset_of<&S::x>::value (как и остальные черты типа), но не может понять магию синтаксиса для него.

14

Решение

Следующее должно работать (кредиты идут в ответ на этот вопрос за идею)

#include <cstddef>

template <typename T, typename M> M get_member_type(M T::*);
template <typename T, typename M> T get_class_type(M T::*);

template <typename T,
typename R,
R T::*M
>
constexpr std::size_t offset_of()
{
return reinterpret_cast<std::size_t>(&(((T*)0)->*M));
}

#define OFFSET_OF(m) offset_of<decltype(get_class_type(m)), \
decltype(get_member_type(m)), m>()

struct S
{
int x;
int y;
};

static_assert(OFFSET_OF(&S::x) == 0, "");

Обратите внимание, что в gcc offsetof макрос расширяется до встроенного расширения, которое можно использовать во время компиляции (см. ниже). Кроме того, ваш код вызывает UB, он разыменовывает нулевой указатель, поэтому даже если он может работать на практике, никаких гарантий нет.

#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

Как указал Люк Дантон, константные выражения не могут включать reinterpret_cast в соответствии со стандартом C ++ 11, хотя в настоящее время gcc принимает код (см. отчет об ошибке здесь). Кроме того, я нашел отчет о дефекте 1384 который
говорит о том, чтобы сделать правила менее строгими, так что это может измениться в будущем.

13

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]