Могу ли я преобразовать указатель на функцию-член в массив символов и обратно, используя reinterpret_cast?

У меня есть код, который выглядит следующим образом:

char member_data[16];

template<typename T>
void set(void (T::*member)(void)) {
memcpy(member_data, (char*) &member, sizeof(member));
}

template<typename T>
void (T::*)(void) get() {
void (T::*member)(void);
memcpy((char*) &member, member_data, sizeof(member));
return member;
}

В полном контексте я могу быть уверен, что set всегда использует тот же тип, что и следующий get,

Можно ли это безопасно переписать для использования reinterpret_cast?

Редактировать:

Этот код делает то же самое, что и выше?

char member_data[16];

template<typename T>
using member_func = void (T::*)();

template<typename T>
void set(member_func<T> member) {
reinterpret_cast<member_func<T>&>(member_data) = member;
}

template<typename T>
member_func<T> get() {
return reinterpret_cast<member_func<T>&>(member_data));
}

Кажется работать

1

Решение

Версия, которая у вас есть в отредактированной части, недействительна: вы не можете получить доступ к произвольный char массив как любой другой тип. Может быть возможно достичь чего-то подобного правильным способом, используя std::aligned_storage<..> вместо равнины char массив.

Если member_data объявлен как

std::aligned_storage<sizeof(member_func<T>), alignof(member_func<T>)>::type member_data;

или (по существу, эквивалентно)

alignas(member_func<T>) char member_data[sizeof(member_func<T>)];

тогда ваш reinterpret_cast<..> подход должен на самом деле работать. Вместо зависимого параметра шаблона sizeof а также alignof выражения, вы можете попробовать использовать любой фиксированный member_func<some_class>, Крайне маловероятно, что реализация имеет разные требования к размеру или выравниванию для указателей на функции-члены разных классов. Если вы хотите быть действительно безопасным, используйте статические подтверждения для проверки.

Можно ли это безопасно переписать для использования reinterpret_cast?

Кроме того, что описано в вашем редактировании, вы можете напрямую привести указатель на функцию-член, например reinterpret_cast<SomeType>(member), только если SomeType также является указателем на тип члена. Так что вы Можно выберите один тип функции указателя на член в качестве «хранилища указателя на функцию универсального члена», если все, что вы делаете с этим значением, это конвертируете его обратно в исходный тип указателя на член.

Вы не можете конвертировать указатель на член в указатель на объект (или наоборот).

В обоих случаях ваш код небезопасен как есть, потому что он переполнит member_data буфер, если sizeof (void (T::*)()) > 16,

И, кстати: первый пример кода уже делает использование reinterpret_cast: Старый стиль приведен к (char*) от void (T::**)() уже эквивалентно reinterpret_cast 😉

4

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

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

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