我注意到伪析构函数调用在使用类型名称时有效,但在使用基本类型时则无效。
typedef int BType;
int b;
b.~BType(); // Legal
b.~int(); // Not legal
可以在an answer to another SO post找到对上述内容的解释。
来自C ++ 11标准的类型名称的定义:
7.1.6.2简单类型说明符,p1
type-name: class-name enum-name typedef-name simple-template-id
当类型说明符是类型名称时,是否有任何其他语言结构有效,但即使 type-name ,它也是基本类型时无效代表一种基本类型,如上所示?
答案 0 :(得分:4)
我认为你不会发现任何其他案件。如果我们查看草案C ++标准附件A语法摘要,我们可以看到 type-name 显示的语法中唯一的其他位置是:
nested-name-specifier:
::
type-name ::
namespace-name ::
decltype-specifier ::
nested-name-specifier identifier ::
nested-name-specifier templateopt simple-template-id ::
和
simple-type-specifier:
nested-name-specifieropt type-name
[...]
这两者都没有提供类似的机会,我们得到的pseduo-destructor具有以下语法:
pseudo-destructor-name:
nested-name-specifieropt type-name :: ~ type-name
nested-name-specifier template simple-template-id :: ~ type-name
nested-name-specifieropt~ type-name
~ decltype-specifier
并在5.2.4
[expr.pseudo]部分中介绍,该部分规定了我们看到的行为:
在点后使用伪析构函数名称。或箭头 - >操作者 表示由type-name表示的非类类型的析构函数 或decltype-specifier。结果只能用作操作数 对于函数调用operator(),以及这样的调用的结果 类型无效。唯一的影响是后缀表达式的评估 在点或箭头之前。
另一方面,我们可以在3.4.3
[basic.lookup.qual] 部分看到嵌套名称说明符的规则,禁止这样的情况:
可以引用类或命名空间成员或枚举器的名称 在:: scope resolution operator(5.1)应用于之后 nested-name-specifier,表示其类,名称空间或 列举。如果是:: scope解析运算符 nested-name-specifier之前没有decltype-specifier,lookup 之前的名称::仅考虑名称空间,类型和 专业化类型的模板。如果找到的名称没有 指定命名空间或类,枚举或依赖类型, 节目形成不良
简单类型说明符的情况不会让我们在那里,因为基本类型已经可以接受这种情况。
答案 1 :(得分:2)
当函数的返回类型是基本类型时,存在差异:
struct X{};
template <class T> auto foo() {
// one liner
[]() -> T { return T{}; }() = T{}; // invalid for T fundamental type
// or more clear:
auto get_t = []() -> T { return T{}; };
get_t() = T{}; // invalid for T fundamental type
}
auto main() -> int {
foo<X>(); // valid
foo<int>(); // invalid
return 0;
}
没有模板,更加清晰:
struct X{};
auto ret_x() -> X { return X{}; }
auto ret_int() -> int { return int{}; }
auto main() -> int {
ret_x() = X{}; // valid
ret_int() = int{}; // invalid
return 0;
}
基本类型的rvalues无法修改。对于其他类型显然不是这种情况,例如,移动操作必须修改它移动的临时值(例如,使拥有指针为nullptr)