Как получить указатель функции-члена деструктора?

Предположим, у меня есть

struct X {
  ~X() {}
};

Каков тип и как получить указатель функции-члена X::~X() в С++ 03?

Я не хочу на самом деле вызывать его, просто используйте в SFINAE, чтобы понять, существует ли деструктор для данного типа.


person bitmask    schedule 02.06.2012    source источник
comment
Деструктор всегда существует...   -  person Oliver Charlesworth    schedule 02.06.2012
comment
@OliCharlesworth: Но как реальная функция? Когда я извлекаю int из стека, функция int::~int не вызывается.   -  person bitmask    schedule 02.06.2012
comment
@bitmask: int не class, поэтому для него нет деструктора.   -  person K-ballo    schedule 02.06.2012
comment
@bitmask: стандарт С++ явно не согласен с вами (вроде); в соответствии с концом раздела [class.dtor] допустимо следующее: typedef int I; I* p; p->I::~I();.   -  person Oliver Charlesworth    schedule 02.06.2012
comment
@OliCharlesworth: я полагаю, что такая инструкция не приведет к какому-либо фактическому коду в результирующем двоичном файле, поскольку для встроенных типов делать нечего, верно? Но я предполагаю, что это означает, что я все равно могу реализовать что-то вроде has_trivial_destructor таким образом.   -  person bitmask    schedule 02.06.2012
comment
@Oli: Это вызов псевдодеструктора, и синтаксис действителен, но он ничего не вызывает. [expr.pseudo] говорит Единственным эффектом является оценка постфиксного выражения перед точкой или стрелкой.   -  person Jonathan Wakely    schedule 02.06.2012
comment
@bitmask: has_trivial_destructor требует поддержки компилятора. Не все свойства типов можно реализовать на чистом C++, и это одно из них. Если вы действительно чувствуете, что вам это нужно, прочтите документацию по вашему компилятору и посмотрите, есть ли у него такая черта. (Вы можете обмануть, загрузив трейты типа boost и просмотрев их реализацию для вашего компилятора, на самом деле не нужно добавлять зависимость в код).   -  person David Rodríguez - dribeas    schedule 02.06.2012


Ответы (1)


Вы не можете получить указатель на функцию ни деструктора, ни конструктора. Тем не менее, деструктор всегда существует для типа, и вы не можете определить, не учитываются ли его private со спецификаторами доступа as в SFINAE.

Что касается вызова деструктора скалярного типа, в стандарте указано [class.dtor]/16:

[Примечание: обозначение явного вызова деструктора можно использовать для любого имени скалярного типа (5.2.4). Это позволяет писать код, не зная, существует ли деструктор для данного типа. Например,

typedef int I;

I* p;

p->I::~I();

-конец примечания]

person K-ballo    schedule 02.06.2012
comment
Спасибо. Моей мотивацией было то, что я могу ускорить определенную часть структуры данных, если не буду вызывать деструкторы некоторых объектов. Поэтому я попытался решить, существует ли нетривиальный деструктор. Любые подсказки? - person bitmask; 02.06.2012
comment
@bitmask: Поскольку ваш вопрос касается C++03, лучше всего использовать признак типа boost::has_trivial_destructor, который работает только в том случае, если компилятор предоставляет соответствующую встроенную функцию. Но если деструктор тривиален, я все равно вызываю его и позволяю компилятору оптимизировать его... - person K-ballo; 02.06.2012
comment
Что ж, мне приходится жить с искалеченным подмножеством C++, так как у меня нет ни буста, ни C++11. Мне не нужно уничтожать один объект, а кучу объектов, но мне не нужно ничего делать, если они тривиальны, поэтому я не ожидаю, что итерация будет оптимизирована, поэтому я хочу запечь это в код. - person bitmask; 02.06.2012
comment
@bitmask: посмотрите, есть ли у вашего покалеченного компилятора уже встроенная функция... в противном случае все ставки сняты - person K-ballo; 02.06.2012
comment
На самом деле это g++, но я не могу использовать boost/11 по другим причинам. - person bitmask; 02.06.2012
comment
@bitmask: И вы действительно верите, что стоимость производительности зависит от уничтожения? Как вы пришли к такому выводу? Если деструктор тривиален, компилятор увидит пустой цикл и, скорее всего, оптимизирует его. Пробег будет разным, но вы можете посмотреть на сгенерированный код и посмотреть, был ли цикл удален из функции. - person David Rodríguez - dribeas; 02.06.2012
comment
@DavidRodríguez-dribeas: Да, я попробовал это для небольшого примера (чтобы я действительно мог понять ассемблер), и, похоже, он правильно оптимизирован, по крайней мере, с -O1. Однако, как вы говорите, мой пробег будет варьироваться, так как я не вижу хорошего способа убедиться, что он будет работать правильно для фактического кода. Тем не менее, у меня, кажется, нет других вариантов, так что спасибо, что указали на это. - person bitmask; 02.06.2012
comment
@bitmask: доверяйте компилятору, я предполагаю, что цикл, который удаляет объект, не будет иметь большой логики. Если это так, то независимо от того, насколько сложен код вокруг цикла, его будет легко оптимизировать. - person David Rodríguez - dribeas; 02.06.2012