为什么不 ~ 后跟 :: 解析
Why doesn't ~ followed by :: parse
在Andrei Alexandrescu关于错误处理的演讲中:
参见c++和超越2012:Andrei Alexandrescu - c++中的系统错误处理(大约30分钟)
Andrei给出了以下代码:
~Expected()
{
using std::exception_ptr;
if (gotHam) ham.~T();
else spam.~exception_ptr();
}
析构函数正在清理包含某种类型T
或std::exception_ptr
的union
。使用placement new
填充联合。
using std::exception_ptr;
是必要的,因为下面的代码不能解析:
else spam.~std::exception_ptr();
这意味着如果你需要显式调用不同命名空间中的类的析构函数,总是需要有一个using指令。
为什么第二个例子不能解析?
下面的代码是一个有效的替代吗?
else delete spam;
这是否与显式调用std::exception_ptr
Andrei使用using std::exception_ptr;
可能是因为他的编译器坏了。
没有必要。没有它,spam.~exception_ptr();
应该可以很好地编译。
3.4.5/3。如果非限定id为~type-name,则在整个后缀表达式的上下文中查找类型-name。如果对象表达式的类型T是类类型C,则在类C的作用域中也查找类型名。
它确实使用gcc编译。
如果出于某种原因需要使用限定名称,spam.std::exception_ptr::~exception_ptr();
也会编译
这里的问题是,~std::exception_ptr()
不是你想调用的函数的真正名称,而只是~exception_ptr()
。而且,由于它属于不同命名空间中的类,它是不可访问的(编辑:尽管根据c++ 11标准中的§3.4.5/3,它应该是可访问的,正如n.m.在他的回答中指出的那样,但是微软编译器是这样做的)。
您可以选择将类带入您的名称空间:使用限定类名进行显式调用:
else spam.std::exception_ptr::~exception_ptr(); // This is legal
至于你的第二个问题,正如R. Martinho Fernandes在评论中正确解释的那样,调用delete
运算符并不仅仅等同于调用析构函数:它还调用了名称笨拙的函数operator delete()
。
语法spam.~std::exception_ptr
是不允许的,因为语法要求id表达式,而~std::exception_ptr
不是,正如Gorpik指出的那样,您需要spam.std::exception_ptr::~exception_ptr()
。但是我不明白为什么需要限定,在描述语法的子句中,提醒了
因为类的名称插入到类的作用域中(第9条),所以类的名称也被认为是该类的嵌套成员。
所以我认为spam.~exception_ptr()
应该是有效的,即使没有使用子句。顺便说一句
namespace ns {
struct Foo {};
}
void f()
{
ns::Foo x;
x.~Foo();
}
用我所能访问的所有g++(包括非常旧的2.95)干净地编译。这似乎证实了我的观点,如果它不能在c++ 11更新的联合类型上下文中工作,那就是实现中的错误。
编辑,在g++ 4.7.1下,使用-std=c++11也可以编译以下代码。
namespace ns {
struct Foo {};
}
struct Bar {};
union U {
ns::Foo f;
Bar b;
};
struct C {
bool b;
U u;
~C() {
if (b)
u.f.~Foo();
else
u.b.~Bar();
}
};
void f()
{
C c;
}
所以Andrei已经被侧边跟踪(要么是他正在使用的编译器中的错误,要么是忘记了类名在类的作用域内导入的事实)尝试解决一个不需要解决的问题。
- 继承函数的重载解析
- 基类中的函数名称解析
- 提升精神:解析布尔表达式并简化为规范范式
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- gcc和c++17的过载解析失败
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 构造函数和转换运算符之间的重载解析
- 未解析的外部符号_MsiLocateComponentW@12.
- '尝试解析可变参数模板时无法推断出'T的模板参数
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- 如何在 cpp 中解析此文件?
- 在C++中使用 gRPC 时未解析的外部符号
- IDE (CLion) 无法解析C++模板类型
- 配置文件解析器仅返回以前的值
- 增强精神解析器规则以检测语句中的特殊结尾
- 将向量解析<string>为字符串
- 使用 jsoncpp 解析 json 数组字符串
- 如何解析后跟分号或换行符的条目(boost::spirit)
- 为什么不 ~ 后跟 :: 解析