我正在编写一个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
可怕的错误。我哪里错了?由于SFINAE,enable_if<false,...>
替代品不应该从分辨率中删除吗? 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 *){}
使用您的语法,您将返回存在的std::enable_if<std::is_trivially_destructible<C>::value>
(因此它不会被SFINAE删除,然后您有两个相同的方法,具有不同的返回类型)
std::enable_if<bool condition, typename T>::type
仅在条件为真时存在(并且等于默认为void
的第二种类型)。
Microsoft say it's a bug ("limitation") of their compiler。
发明复杂的基于模板的变通方法是一项有趣的智力挑战,但在对真实产品进行代码审查时,我会把任何这样的事情扔得比你说的“过度工程”更快。
template <typename C>
void destroy (C * c) // <-- this is the 'c' that the warning is referring to
{
(void)c; // shut up you stupid compiler
c->~C ();
}
关于1.缺少某些东西(代码/警告/错误消息)。
这很好用:
template <typename T>
void destroy(T* p) {
p->~T();
}
int main()
{
int* i;
destroy(i);
return 0;
}
用g ++编译-std = c ++ 11 -Wall -pedantic