Я пишу C++ 11 STL-совместимый распределитель, и мне было интересно, как определить типы, для которых это безопасно не назвать их деструктор (в allocator<T>::destroy
метод.)Обнаружение, когда тип не нужен для вызова его деструктора
Я уже написал распределитель (простой), и насколько я могу судить, он действительно работает. Поэтому я спрашиваю, что я получаю предупреждения в своем коде (т.е. в destroy
методе моего распределителем.) Я использую VS2013 (VC12) на самом высоком уровне предупреждения, а также предупреждение:
warning C4100: 'c' : unreferenced formal parameter
в этом методе:
template <typename T>
class MyAlloc
{
...
template <typename C>
void destroy (C * c) // <-- this is the 'c' that the warning is referring to
{
c->~C();
}
...
};
Как вы можете видеть, как предупреждение и код довольно просты и понятны. Мне кажется, что предупреждение выдается, потому что некоторые из классов, к которым этот распределитель используется, не имеют деструкторов (например, потому что они POD и т. Д.). Впоследствии компилятор удаляет вызов деструктору в вышеуказанной функции, когда для таких классов создается экземпляр распределителя, а затем, видя, что тело функции пустое и аргумент не используется, выдает предупреждение.
Я думаю, что я могу написать две версии вышеописанного метода destroy
, перегружая с помощью enable_if
и оставляя тело пустым и аргумент, не названный в перегрузке, который предназначен для классов, которые не нуждаются в уничтожении. Будет ли это работать?
С другой стороны, это предупреждение является очень небольшим неудобством. Я могу отключить это конкретное предупреждение, и это не окажет большого влияния на мою кодовую базу. В конце концов, это вряд ли полезно.
Однако, если я попытаюсь изменить свой код и обнаружить классы, которые не нуждаются в уничтожении, но делайте это неудовлетворительно и плохо, я открываю шлюзы для всех видов боли и страданий. Потому что, если мне не удастся уничтожить экземпляр класса, который делает, нужно уничтожить, только боги знают, что может (и будет) идти не так! Поэтому, если нет 100% надежного и надежного метода обнаружения таких классов и управления ими, я предпочитаю оставить предупреждение и даже отправить с предупреждением.
Повторим, мой вопрос состоит из трех частей:
- Является ли мой анализ причины предупреждения правильно?
- Как определить, когда безопасно не вызывать деструктор типа. Другими словами, когда деструктор типа не имеет абсолютно никакого эффекта и как я могу его обнаружить (используя черты типа и т. Д.)?
- Является ли это обнаружение всегда надежным и полностью надежным?
И бонусный вопрос:
Я попробовал эту перегрузку только увидеть бы ли он работать:
template <typename C>
std::enable_if<std::is_trivially_destructible<C>::value>
destroy (C *)
{
}
template <typename C>
std::enable_if<!std::is_trivially_destructible<C>::value>
destroy (C * c)
{
c->~C();
}
Обратите внимание, что я не говорю, что использование std::is_trivially_destructible<>
это путь ; Я просто хотел попробовать посмотреть, работает ли в этом контексте enable_if
.Но теперь я получаю много ошибок, как это:
error C2668: 'MyAlloc<Whatever>::destroy' : ambiguous call to overloaded function
could be 'std::enable_if<false,void> MyAlloc<Whatever>::destroy<SomeType>(C *)'
or 'std::enable_if<true,void> MyAlloc<Whatever>::destroy<SomeType>(C *)'
Кажется, что я делаю что-то ужасно неправильно с enable_if
. Где я иду не так? Не следует ли исключить альтернативу enable_if<false,...>
из резолюции из-за SFINAE? Идет ли SFINAE в классе? Я также буду благодарен за любую помощь в этом отношении.
Правильный синтаксис 'шаблон имяТипа станд :: enable_if <станд :: is_trivially_destructible :: значение> :: тип уничтожить (C *) {}' –
Jarod42
станд :: has_virtual_destructor также может быть полезно? – hevi
@hevi: У многих типов нет (и на самом деле не нужны) виртуальные деструкторы, но у них все еще есть нетривиальные деструкторы, которые должны быть вызваны. – yzt