Могу ли я вызвать виртуальный деструктор, используя указатель на функцию? - PullRequest
0 голосов
/ 10 октября 2018

У меня есть класс Data, который может содержать указатель на объект.Я хочу иметь возможность позже вызывать деструктор вручную, для чего мне нужно, чтобы его адрес хранился в переменной, но кажется, что взятие адреса конструктора / деструктора запрещено.Есть ли способ обойти это?

struct Data {

  union {
    long i;
    float f;
    void* data_ptr;
  } _data;

  std::type_index _typeIndex;
  void (*_destructor_ptr)();

  template<typename T>
  void Init() {
  if constexpr (std::is_integral<T>::value) {
    //
  }
  else if constexpr (std::is_floating_point<T>::value) {
    //
  }
  else {
    _data.data_ptr = new T;
    _typeIndex = std::type_index(typeid(T));
    _destructor_ptr = &T::~T; // << -- can't do this
  }
}

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

Существует также это решение, если ваш компилятор не поддерживает лямбды:

template<typename T>
struct DestructorHelper {
  static void Destroy(void * v) {
    delete static_cast<T*>(v);
  }
};

и использует его как:

_destructor_ptr = &DestructorHelper<T>::Destroy;
0 голосов
/ 10 октября 2018

Я также добавлю решение для умных указателей:

template <class T>
struct DataPtrDeleter
{
    void operator()(void * p) { delete (T*)p; }
}

std::shared_ptr<void*> data_ptr(new T, DataPtrDeleter<T>());
//or
std::unique_ptr<void*, DataPtrDeleter<T>> data_ptr(new T, DataPtrDeleter<T>());
0 голосов
/ 10 октября 2018

Храните лямбда, соответственно преобразованную:

void (*_destructor_ptr)(void *v);

// ...

_destructor_ptr = [](void* v) { delete static_cast<T*>(v); };

Обратите внимание, что вы должны передать _data.data_ptr для v.Если вы намереваетесь хранить простой указатель на функцию, лямбда может не захватывать или неявно ссылаться на _data.data_ptr.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...