【问题标题】:Why can't a qualified type name in an explicit destructor call be parsed correctly?为什么不能正确解析显式析构函数调用中的限定类型名称?
【发布时间】:2015-02-28 23:26:34
【问题描述】:

考虑一个例子。

#include <string>

struct S {
    S() {
        new (&s) std::string("hi");
    }

    ~S() {
        // does not compile
        // s.~std::string();

        // compiles
        using std::string;
        s.~string();
    }

    union {
        std::string s;
    };
};

为什么注释掉的部分不能编译?

我从 clang 得到的错误信息显示编译器将 std 本身解析为一种类型。

对象销毁表达式中的标识符“std”未命名类型

为什么编译器不能确定std::string 是类型?这在某种程度上是模棱两可的吗?

我是从 Andrei Alexandrescu 的演讲中了解到这一点的。现在是 37:10。他很快发现如果类型名称是合格的,这“不会解析”,但没有解释原因。

http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C

(我使用“解析”这个词主要是因为他这样做了,我没有想到更好的词。不要读得太深。我不是说编译器做错了什么。)

【问题讨论】:

  • ~unqualified-id 的一部分,它后面只能跟 class-name decltype-specifier,或在伪析构函数中调用 type-name
  • 因为~string() 不是std::namespace 的成员?
  • 根据gcc,一个有效的写法是s.std::string::~string();。不过,clang 不喜欢它。
  • 还没有人提到这个,但是s.~basic_string();是正确的方法。
  • 至于为什么标准作者没有指定s.~string();被接受(没有using)..不知道那里。 ~ 后面只有一种可能的东西,那就是析构函数的名称,所以我不明白为什么这里不能使用所有可能的查找类型。没有歧义的可能性,它要么找到析构函数,要么什么也没找到。事实上,为什么不允许s.~();

标签: c++ destructor placement-new


【解决方案1】:

原因是std::string 实际上并没有命名类类型。除此之外,这意味着不存在名为 ~string() 的析构函数。

std::string&lt;string&gt; 中实际上是一个 typedef(替代名称),用于命名为 std::basic_string&lt;char&gt; 的模板类类型的特化。

typedef some_class_name another_name 形式的 typedef 不会导致存在名为 ~another_name 的析构函数。

【讨论】:

  • 我通过将其称为 s.std::basic_string&lt;char&gt;::~basic_string&lt;char&gt;(); 来让示例在没有 using 的情况下工作。我不知道你的最后一句话是否完全准确。使用using,析构函数可以称为~string
猜你喜欢
  • 2018-03-07
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2011-12-13
  • 1970-01-01
  • 2014-08-26
  • 2015-08-21
相关资源
最近更新 更多