8.2 歧义消解
8.2 歧义消解
1、由函数式转型和6.8所述声明(声明符以左括号开头)的相似性而引起的歧义也会出现在声明的上下文中。这时,构造体可能为参数名被冗余的圆括号括起来的函数声明(如int f(int (n))),也可能是具有函数式转型初始化体的对象声明(如int n(int(1.0)))。同6.8一样,歧义消解的方案是将任何能当作声明的构造体看作是一个声明(比如:优先将int (n)看作是对int型变量n的声明,而不是对变量n的强制整型转换;这样导致的一个直接后果是将int f(int (n))解析为函数声明,而不是被n初始化的整型变量f的声明。)。[注:也可通过下列方法对一个可能会引起上述歧义的声明进行显式的消歧:使用非函数式的转型;使用=对变量进行初始化;去掉参数名外冗余的括号。]例如:
struct S {
S(int);
};
void foo(double a)
{
S w(int(a)); // function declaration
S x(int()); // function declaration
S y((int)a); // object declaration
S z = int(a); // object declaration
}
2、由函数式转型和type-id(通常是函数类型)之间的相似性而引发的歧义可能在不同的上下文中出现。这时,构造体可能为一个带函数式转型的表达式,或一个类型的声明。消解的方案是将任何在句法上可为type-id的构造体看作是一个type-id(也就是说优先将具有上述歧义的构造体看作是一个type-id)。
3、例如:
#include <cstddef>
char *p;
void *operator new(size_t, int);
void foo() {
const int x = 63;
new (int(*p)) int; // new-placement expression
new (int(*[x])); // new type-id
}
4、另一个例子,
template <class T>
struct S {
T *p;
};
S<int()> x; // type-id
S<int(1)> y; // expression (ill-formed)
5、另一个例子,
void foo()
{
sizeof(int(1)); // expression
sizeof(int()); // type-id (ill-formed) 函数不能做sizeof的参量
// 不过在vc6能成功编译此代码,结果返回4,
// 证明vc6将sizeof中的int()解析为整型表达式而不是函数
}
6、另一个例子,
void foo()
{
(int(1)); //expression
(int())1; //type-id (ill-formed)
}
7、当type-name嵌套在圆括号内时,函数声明中的parameter-declaration-clause或作为sizeof和typeid操作符参量的type-id,会导致另一个歧义。在这种情况下,构造体可能是一个函数指针类型的参数声明,也可能是一个在declarator-id周围有冗余括号的参数声明。消解方法是将type-name看作simple-type-specifier而不是declarator-id。例如:
class C { };
void f(int(C)) { } // void f(int (*fp)(C c)) { }
// not: void f(int C);
int g(C);
void foo() {
f(1); //error: cannot convert 1 to function pointer
f(g); //OK
}
另一个例子,
class C { };
void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));
// not: void h(int *C[10]);