Является ли это использованием неопределенного поведения reinterpret_cast?

#c #casting

#c #Кастинг

Вопрос:

Я не уверен в этом фрагменте кода:

 #include <functional>
#include <list>
#include <iostream>

void f() { std::cout << "HI!n"; }

struct fobj
{
    void operator()() const { std::cout << "Bye!n"; }
};

using slot_t = std::function<void()>;
std::list<slot_t> slot_list;

template<class F>
inline std::size_t insert_slot(F f)
{
    auto it = slot_list.insert(slot_list.begin(), f);
    return reinterpret_cast<std::size_t>(amp;*it);
}

inline slot_tamp; recover_slot(std::size_t conn_id)
{ return *reinterpret_cast<slot_t*>(conn_id); }

int main()
{
   std::size_t conn1_id = insert_slot(f);
   std::size_t conn2_id = insert_slot(fobj());

   recover_slot(conn1_id)(); // HI!
   recover_slot(conn2_id)(); // Bye!
}
  

Я не вижу reinterpret_cast<T*>(some_size_t) никаких отличий от static_cast<T*>(some_void_ptr) , но я не совсем уверен, насколько рискованно первое.

Комментарии:

1. Это может быть немного меньше UB, если вы используете uintptr_t вместо size_t .

2. На самом деле я не уверен, но uintptr_t существует по какой-то причине.

3. UB или not…it это ужасно.

4. «Тип size_t — это определенный реализацией целочисленный тип без знака, который достаточно велик, чтобы содержать размер в байтах любого объекта». Обычно он достаточно большой, чтобы содержать адрес, но существуют архитектуры или ограничения среды, где это не выполняется. Вы могли бы добавить a static_assert , чтобы проверить это sizeof(size_t) >= sizeof(amp;f) . uintptr_t достаточно большой, чтобы содержать адрес, но является необязательным типом, который может не предоставляться. Было бы безопаснее использовать его, а не size_t .

5. Это явно разрешено для reinterpret_cast указателя на достаточно большой интегральный тип и обратно; результат гарантированно будет равен исходному указателю. Итак, предполагая size_t , что он достаточно большой, или вы переключаетесь на uintptr_t , ваш пример четко определен. Тем не менее, неясно, почему вы хотите выполнить цикл через целое число. Почему бы не обойти slot_t* ?