c – 当类型不需要调用其析构函数时检测

我正在编写一个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也是在课堂上发生的吗?我也会感谢你在这方面的任何帮助.

最佳答案

Is my analysis of the cause of the warning correct?

我认同.有几种方法可以静默一个未使用的变量警告(通常有特定的宏/函数来做这件事很有帮助)

How can I determine when it is safe not to call a type’s destructor. In other words, when does a type’s destructor has absolutely no effect and how can I detect this (using type traits, etc.)?

我会沉默警告.
但如果我必须使用特征,我会使用std :: is_trivially_destructible.

Is this detection always reliable and completely robust?

似乎没有完全改变C 1y的定义.

About your error:

正确的语法是(注意typename .. :: type)

template <typename C>
typename std::enable_if<std::is_trivially_destructible<C>::value>::type
destroy (C *){}

使用语法,返回std :: enable_if< std :: is_trivially_destructible< C> :: value>哪个存在
(所以它不会被sfinae删除然后你有两个相同的方法,具有不同的返回类型)

std :: enable_if< bool condition,typename T> :: type仅在条件为真时存在(并且等于第二个默认为void的类型).

点赞