Почему оператор вызова функции для временных объектов иногда может интерпретироваться как объявление, которое не скрывает параметр? - PullRequest
3 голосов
/ 07 марта 2019

Мой вопрос похож на этот ответ , но с одной большой разницей.

Если я попытаюсь скомпилировать следующее,

void test(string x){
  int x = 5;
  cout << x << endl;
}

Я получаю ожидаемое предупреждение:

In function ‘void test(std::__cxx11::string)’:
error: declaration of ‘int x’ shadows a parameter
    int x = 5;
        ^

Теперь, чтобы добраться до сути моего вопроса; если у меня есть тип с оператором вызова функции, как показано ниже:

struct foo{
  string bar;
  foo(const string& bar) : bar(bar) { }
  void operator()(){
    cout << "my bar is \"" << bar << '"' << endl;
  }
};

Я могу создать временный объект и вызвать его оператор () с помощью foo("this will print")(); или foo{"this will also print"}();

Если я попытаюсь сделать следующее, я получу ошибку компилятора, которая является ожидаемой и может быть объяснена постом, на который я ссылаюсь выше.

void redeclaration_error(){
  string x("lol");
  foo(x)();
}

Однако, здесь все странно:

void hmm1(string str){
  foo(str)();
}
void hmm2(string str){
  foo{str}();
}

Хотя hmm2 будет выводить аргумент при вызове, hmm1 абсолютно ничего не сделает. Это ожидается, так как тело hmm1 не делает ничего, кроме объявления str типа foo. Однако в области hmm1, str уже объявлено как тип string из параметра функции, так почему это не приводит к ошибке компилятора, такой как error: declaration of ‘foo str‘ shadows a parameter?

Я понимаю, что компилятор интерпретирует foo(str)(); как объявление, и такие строки, как foo(str).operator()(); и (foo(str))(); будут интерпретироваться как создание временного объекта foo и вызов их оператора вызова функции, но почему это нормально? объявить переменную с тем же именем, что и параметр в этом случае?


Вот и ссылка Ideone, где я играл с этим.

1 Ответ

1 голос
/ 07 марта 2019

Более простая программа для создания той же проблемы (дополнительные скобки - красная сельдь):

void f(int x)
{
    void x();
}

Это неверно из-за C ++ 17 [basic.scope.block] / 2:

[...] Имя параметра не должно быть повторно объявлено во внешнем блоке функции определение ни в самом внешнем блоке любого обработчика, связанного с function-try-block.

Если компилятор принимает этот код, то это ошибка компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...