Неоднозначность, возникающая из-за сходства между приведением в стиле функции и объявлением, упомянутым в, [stmt.ambig] также может возникать в контексте объявления. В этом контексте выбор находится между объявлением функции с избыточным набором круглых скобок вокруг имени параметра и объявлением объекта с приведением в стиле функции в качестве инициализатора. Как и в случае неоднозначности, упомянутой в [stmt.ambig], резолюция должна рассматривать любую конструкцию, которая могла бы быть объявлением, объявлением. [ Note: В объявлении можно явно устранить неоднозначность, добавив круглые скобки вокруг аргумента. Двусмысленности можно избежать, используя синтаксис копирования-инициализации или инициализации списка, или используя приведение без функционального стиля. ] [ — end note Example:
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 y((int)a); // object declaration S z = int(a); // object declaration }
— end example ]
Неоднозначность может возникнуть из-за сходства между приведением в стиле функции и типом type-id. Решение состоит в том, что любая конструкция, которая могла бы быть a type-id в своем синтаксическом контексте, должна считаться a type-id. [ Example:
template <class T> struct X {}; template <int N> struct Y {}; X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expression void foo(signed char a) { sizeof(int()); // type-id (ill-formed) sizeof(int(a)); // expression sizeof(int(unsigned(a))); // type-id (ill-formed) (int())+1; // type-id (ill-formed) (int(a))+1; // expression (int(unsigned(a)))+1; // type-id (ill-formed) }
— end example ]
Другая двусмысленность возникает в случае, parameter-declaration-clauseкогда a заключено type-name в круглые скобки. В этом случае выбор находится между объявлением параметра типа указателя на функцию и объявлением параметра с избыточными круглыми скобками вокруг declarator-id. Решение состоит в том, чтобы рассматривать type-name как a, simple-type-specifier а не как a declarator-id. [ Example:
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]);
— end example ]