使用decltype和/或std::remove_reference调用析构函数

3

使用decltype和/或std :: remove_reference,调用析构函数(而不使用operator delete)是否可能?以下是一个示例:

#include <iostream>
#include <type_traits>

using namespace std;

class Test
{
    public:
    Test() {}
    virtual ~Test() {}
};

int main()
{
    Test *ptr;

    ptr->~Test(); // works
    ptr->~decltype(*ptr)(); // doesn't work
    ptr->~std::remove_reference<decltype(*ptr)>::type(); // doesn't work

return 0;
}

不,这是不可能的。 - Andy Prowl
3
析构函数不是一种类型。 - Pete Becker
4
你可以使用函数模板来显式调用析构函数(通过类型推断)。不过我不确定你会得到什么好处。 - dyp
DyP,模板是一个可能的解决方案。谢谢! - user1266334
3个回答

5

当您只有一个限定类型名称时,可以使用别名模板来获取未限定的类型名称。以下代码应该可以实现:

template<typename T> using alias = T;
ptr->~alias<std::remove_reference<decltype(*ptr)>::type>();

请注意,如果remove_reference的方法可行,即使通过限定类型名称,您也会禁止虚拟析构函数调用,因此这仍然很危险。通过使用别名模板,虚拟析构函数仍然可以正常工作。

请注意,GCC4.8似乎接受。

ptr->std::remove_reference<decltype(*ptr)>::type::~type();

Clang不支持这个。我已经放弃尝试理解析构函数名查找的工作了(如果你看过clang源代码,你会发现clang开发人员也没有遵循规范,因为他们认为这里没有意义)。存在DR涵盖析构函数调用语法以及它们是如何混乱的。因此,我建议在此处不使用任何复杂的语法。


你确定 decltype-specifiers 不被允许吗?例如 [expr.prim.general]/8 "以 ~ 为前缀的类名或 decltype-specifier 表示一个析构函数"。 - dyp
@DyP我认为我没有说decltype-specifiers是不允许的。但这是无关紧要的,因为decltype修饰符将表示引用类型,因此不能在他的示例中使用。 - Johannes Schaub - litb
请您能否再详细解释一下?我不明白在什么情况下虚析构函数不会被调用。 - user1266334
@user1266334 我建议你为此开一个不同的问题。 - Johannes Schaub - litb

1
如果您的编译器不支持使用模板命令,您可以执行以下操作:
定义模板结构体:
template<class T> struct unwind_alias { static VOID destroy(T* ptr) { ptr->~T(); }; };

使用它来销毁对象。
unwind_alias<std::remove_reference<decltype(*ptr)>::type>::destroy(ptr);

希望这能帮助到任何人。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接