【问题标题】:Calling destructor with decltype and\or std::remove_reference使用 decltype 和\或 std::remove_reference 调用析构函数
【发布时间】:2013-06-24 02:05:23
【问题描述】:

是否可以使用 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;
}

【问题讨论】:

  • 不,不可能。
  • 析构函数不是类型。
  • ... 但您可以使用函数模板显式调用 dtor(推断类型)。不过,不确定你会得到什么。
  • DyP,模板是一种可能的解决方案。谢谢!

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


【解决方案1】:

当您只有一个限定类型名称时,您可以使用别名模板来获取一个非限定类型名称。以下应该工作

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 说明符吗?例如[expr.prim.general]/8 "以~为前缀的类名或decltype-specifier表示析构函数"
  • @DyP 我想我没有声明不允许使用 decltype-specifiers。但这无关紧要,因为 decltype 说明符将表示引用类型,因此不能在他的示例中使用。
  • 请您再解释一下好吗?我不明白什么时候不会调用虚拟析构函数。
  • @user1266334 我建议为此打开一个不同的问题。
【解决方案2】:

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

定义模板结构:

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

用它来销毁对象

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

希望对大家有所帮助。

【讨论】:

    【解决方案3】:

    对于 C++17,您也可以只使用std::destroy_at

    【讨论】:

      猜你喜欢
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-15
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多