yzt*_*yzt 5 c++ templates type-traits
我正在编写一个 C++11 STL 兼容的分配器,我想知道如何检测不调用其析构函数(在allocator<T>::destroy方法中)是安全的类型。
我已经编写了分配器(一个简单的分配器),据我所知,它确实有效。我问的原因是我在代码中收到警告(即在destroy分配器的方法中)。我正在使用最高警告级别的 VS2013 (vc12),警告是:
warning C4100: 'c' : unreferenced formal parameter
Run Code Online (Sandbox Code Playgroud)
在这个方法中:
template <typename T>
class MyAlloc
{
...
template <typename C>
void destroy (C * c) // <-- this is the 'c' that the warning is referring to
{
c->~C ();
}
...
};
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,警告和代码都非常简单明了。在我看来,发出警告是因为该分配器所使用的某些类没有析构函数(例如,因为它们是 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 ();
}
Run Code Online (Sandbox Code Playgroud)
请注意,我并不是说使用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 *)'
Run Code Online (Sandbox Code Playgroud)
看来我正在做一些非常错误的事情enable_if。我哪里错了?难道不应该enable_if<false,...>因为 SFINAE 而从决议中删除替代方案吗?SFINAE 也在课堂范围内发生吗?我也将感谢在这方面的任何帮助。
我对警告原因的分析是否正确?
我想是这样。有多种方法可以消除未使用的变量警告(通常使用特定的宏/函数来做到这一点很有帮助)
如何确定何时不调用类型的析构函数是安全的。换句话说,什么时候类型的析构函数完全没有效果,我如何检测到这一点(使用类型特征等)?
我会让警告保持沉默。但如果我必须使用特征,我会使用std::is_trivially_destructible.
这种检测是否始终可靠且完全可靠?
看起来不完全,因为他们改变了 C++14 的定义。
关于您的错误:
正确的语法是(注意typename.. ::type)
template <typename C>
typename std::enable_if<std::is_trivially_destructible<C>::value>::type
destroy (C *){}
Run Code Online (Sandbox Code Playgroud)
使用您的语法,您返回std::enable_if<std::is_trivially_destructible<C>::value>存在的内容(因此它不会被 SFINAE 删除,然后您有两个具有不同返回类型的相同方法)
std::enable_if<bool condition, typename T>::type仅当条件为真时才存在(并且等于默认为 的第二种类型void)。