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

时间:2013-06-26 19:06:57

标签: c++ c++11 std destructor decltype

是否可以使用decltype和\或std :: remove_reference调用析构函数(不使用运算符删除)?这是一个例子:

#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;
}

3 个答案:

答案 0 :(得分: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。因此,我建议不要在这里使用任何复杂的语法。

答案 1 :(得分:1)

如果您的编译器不支持使用命令模板,您可以执行以下操作:

定义模板结构:

template<class T> struct unwind_alias { static VOID destroy(T* ptr) { ptr->~T(); }; };

用它来销毁对象

unwind_alias<std::remove_reference<decltype(*ptr)>::type>::destroy(ptr);

希望它能帮助任何人。

答案 2 :(得分:0)

使用C ++ 17,您也可以只使用Kotlinx-metadata