我正在编写一个与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也是在课堂上发生的吗?我也会感谢你在这方面的任何帮助。
答案 0 :(得分:1)
我对警告原因的分析是否正确?
我是这么认为的。有几种方法可以使未使用的变量警告静音(并且通常具有特定的宏/函数来执行此操作是有帮助的)
我会沉默警告。 但如果我必须使用特征,我会使用如何确定何时可以安全地不调用类型的析构函数。换句话说,类型的析构函数什么时候完全没有效果?如何检测它(使用类型特征等)?
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
的第二种类型)。
答案 1 :(得分:1)
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 ();
}
答案 2 :(得分:0)
关于1.缺少某些东西(代码/警告/错误消息)。
这很好用:
template <typename T>
void destroy(T* p) {
p->~T();
}
int main()
{
int* i;
destroy(i);
return 0;
}
使用g ++编译-std = c ++ 11 -Wall -pedantic