Tra*_*ian 12 c++ language-lawyer
C++程序(有点出乎意料,起初对我来说)编译并运行正常,除了在结尾处注释的行main()
,如果它被取消注释则是编译时错误.
#include <typeinfo>
#include <iostream>
struct Foo {
int x;
};
template <typename T>
void create(char *buffer)
{
std::cout << "creating " << typeid(T).name() << std::endl;
new (buffer) T();
}
template <typename T>
void destroy(char *buffer)
{
std::cout << "destroying " << typeid(T).name() << std::endl;
((T*)buffer)->~T();
}
int main(int argc, char **argv)
{
char buffer[sizeof(Foo) > sizeof(bool) ? sizeof(Foo) : sizeof(bool)];
// create/destroy Foo via template function calls
create<Foo>(buffer);
destroy<Foo>(buffer);
// now do the above explicitly...
new (buffer) Foo();
((Foo*)buffer)->~Foo();
// create/destroy bool via template function calls
create<bool>(buffer);
destroy<bool>(buffer);
// now do the above explicitly...
new (buffer) bool();
// ((bool*)buffer)->~bool(); // oops, doesn't work
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我从中得知C++(或者至少是g ++的C++思想)允许对模板参数类型进行"显式析构函数调用",即使手动执行类型替换也会导致语法错误(因为bool
实际上并没有真正的析构函数来调用).
为了更明确,行:
((T*)buffer)->~T();
Run Code Online (Sandbox Code Playgroud)
当T在a上实例化时编译并运行正常bool
,但对实际执行相同的操作bool
:
((bool*)buffer)->~bool();
Run Code Online (Sandbox Code Playgroud)
是语法错误.
我发现这种行为,因为我正在进行模板元编程并发现它非常有用,所以我猜它是标准的,并且专门用于处理像我上面那样的案例.有没有人确切知道这是否真的如此,并且当这种行为被标准化时,如果是这样的话?
此外,任何人都可以指出标准中的确切措辞是什么,以及它允许的情况范围?(我不擅长阅读标准,所以我很难自己解决这个问题.)
T.C*_*.C. 11
这确实是有效的C++(据我所知,从C++ 98开始),被称为伪析构函数调用.N4431§5.2.4[expr.pseudo]:
1 在点或箭头 运算符后使用伪析构函数名称表示由type-name或decltype-specifier表示的非类型类型的析构函数 .结果只能用作函数调用运算符的操作数,并且这种调用的结果具有类型.唯一的效果是在点或箭头之前评估 后缀表达式.
.
->
()
void
2点运算符的左侧应为标量类型.箭头操作符的左侧应是指向标量类型的指针.此标量类型是对象类型.对象类型的cv非限定版本和伪析构函数名称指定的类型 应为相同类型.此外,表单的伪析构函数名称中的两个类型名称
Run Code Online (Sandbox Code Playgroud)nested-name-specifier_opt type-name :: ~ type-name
应指定相同的标量类型.
甲伪析构函数名是(第5.2节[expr.post])之一:
nested-name-specifier_opt type-name :: ~ type-name
nested-name-specifier template simple-template-id :: ~ type-name
~ type-name
~ decltype-specifier
Run Code Online (Sandbox Code Playgroud)
虽然类型名称是中的一个(§7.1.6.2[dcl.type.simple])
class-name
enum-name
typedef-name
simple-template-id
Run Code Online (Sandbox Code Playgroud)
bool
不是类型名称,因此~bool()
版本是语法错误.在模板内部,模板类型参数是typedef-name(§14.1[temp.param]/p3),它是一个类型名称,因此~T()
版本编译.
归档时间: |
|
查看次数: |
490 次 |
最近记录: |