Как "A (tmpVector)"; то же, что и "A tmpVector"?

Этот вопрос содержит этот фрагмент кода:

A::A(const char *pc) {
    A(string(pc));
}

A::A(string s) {
    vector<string> tmpVector;
    tmpVector.push_back(s);
    A(tmpVector); // <-- error
}

// Constructor
A::A(vector<string> filePathVector) {
}

Проблема заключается в том, что A(tmpVector); конфликтует с vector<string> tmpVector;:

error: conflicting declaration 'A  tmpVector'
error: 'tmpVector' has a previous declaration as 'std::vector<std::basic_string<char> > tmpVector'

Ответ говорит:

Это

А (tmpVector);

совпадает с этим

A tmpVector;//но уже есть объект с именем tmpVector

С добавленным комментарием:

В этом контексте() являются излишними.

Мой вопрос: почему скобки излишни? Что именно в спецификации С++ 11 делает так? Я этого раньше не видел.

Ответ 1

Из §8 [dcl.decl] стандарта:

Деклараторы имеют синтаксис:

declarator:
    ptr-declarator
    noptr-declarator parameters-and-qualifiers trailing-return-type
ptr-declarator:
    noptr-declarator
    ptr-operator ptr-declarator
noptr-declarator:
    declarator-id attribute-specifier-seq_opt
    noptr-declarator parameters-and-qualifiers
    noptr-declarator [ constant-expression_opt] attribute-specifier-seq_opt
    ( ptr-declarator )

(Остаток грамматики опущен).

В частности, обратите внимание, что

  • A ptr-declarator является declarator.
  • Что-то в форме ( ptr-declarator ) есть noptr-declarator, которое в свою очередь является ptr-declarator.

Другими словами, вы можете иметь столько пар круглых скобок, сколько хотите, и это все еще декларатор. Теперь это вызывает двусмысленность в таких случаях, как T(x);, что разрешено в §6.8 [stmt.ambig] стандарта:

Существует двусмысленность в грамматике, включающая выражения-выражения и объявления: выражение выражение с функцией-стиль явное преобразование типа (5.2.3), поскольку его самое левое подвыражение может быть неотличимы от декларации, где начинается первый декларатор с. (В этом случае утверждение является объявлением.

Пример, сопровождающий этот параграф, непосредственно охватывает этот случай:

class T {
// ...
public:
    T();
    T(int);
    T(int, int);
};

T(a);        // declaration
T(*b)();     // declaration
T(c)=7;      // declaration
T(d),e,f=3;  // declaration
extern int h;
T(g)(h,2);   // declaration