显式调用`int`析构函数 - 为什么需要类型别名?

时间:2017-09-26 14:50:38

标签: c++ language-lawyer destructor c++17 primitive-types

以下计划......

int main()
{
    int{1}.~int();
}

无法在上编译(请参阅conformance viewer

  • clang ++ trunk,-std=c++1z

  • g ++ trunk,-std=c++1z

  • CL 19 2017

int ...

引入类型别名
int main()
{
    using X = int;
    int{1}.~X();
}

...使程序在所有前面提到的编译器上有效,没有警告(参见conformance viewer

为什么在调用int的析构函数时需要类型别名?这是因为int不是销毁调用的有效语法元素吗?

1 个答案:

答案 0 :(得分:9)

它的工作原理是因为语法没有为内置类型做出规定,但确实为别名做了规定:

[expr.post]/1

postfix-expression:
    postfix-expression . pseudo-destructor-name
    postfix-expression -> pseudo-destructor-name

pseudo-destructor-name:
    ~ type-name
    ~ decltype-specifier

[dcl.type.simple]/1

type-name:
  class-name
  enum-name
  typedef-name
  simple-template-id

您可以想象type-name下的每个变量代表什么。对于手头的情况,[expr.pseudo]/1指定它只是void表达式:

  

在点后使用伪析构函数名称。或箭头 - >操作者   表示由type-name表示的非类类型的析构函数   或decltype-specifier。结果只能用作操作数   对于函数调用operator(),以及这样的调用的结果   类型无效。唯一的影响是后缀表达式的评估   在点或箭头之前。

有趣的是,你应该能够在没有别名的情况下做到这一点(如果你有一个命名对象),因为伪析构函数调用也适用于decltype说明符:

auto a = int{1};
a.~decltype(a)();