почему `std :: istreambuf_iterator <char>` рассматривается как объявление функции при построении строки? - PullRequest
1 голос
/ 21 февраля 2020

Многие кодеры могут запутаться в этом коде:

int main() {
  std::ifstream ifs("filename", std::ios::binary);
  std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
  //                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
  ...
}

Я хотел бы понять этот код ясно, поэтому вопрос:

  1. Почему std::istreambuf_iterator<char>(ifs) заключено в (, )?

  2. Как определить этот код, если снять здесь скобки? и

  3. Как определить код, если мы не снимаем скобки?

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 21 февраля 2020

В объявлениях деклараторы могут быть заключены в скобки.

Рассмотрим следующее объявление функции

void f( int ( x ), int ( y ) );

В этом объявлении объявлена ​​функция с двумя параметрами типа int.

В декларации имена идентификаторов могут быть опущены.

Таким образом, вы можете написать

void f( int (), int () );

Это объявление, в свою очередь, объявляет функцию, которая принимает два параметра типа функции int().

Итак, эта конструкция

std::string content(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());

может рассматриваться компилятором как объявление функции, имеющей тип возвращаемого значения std :: string и с первым параметром типа std::istreambuf_iterator<char> и идентификатором ifs и вторым параметром с тип функции istreambuf_iterator<char>().

Чтобы отличить guish объявление от выражения, используются круглые скобки, такие как

std::string content( ( std::istreambuf_iterator<char>(ifs) ), std::istreambuf_iterator<char>());

или фигурные скобки

std::string content(std::istreambuf_iterator<char>{ ifs }, std::istreambuf_iterator<char>());

Вот демонстрационная программа, которая показывает, как могут выглядеть объявления в объявлениях параметров.

#include <iostream>

void f( int ( x ), int ( y ) )
{
    std::cout << "x = " << x << ", y = " << y << '\n';
}

void f( int(), int() );

void f( int g(), int h() )
{
    std::cout << g() + h() << '\n';
}    

int g() { return 100; }

int main()
{
    f( 10, 20 );    

    f( g, g );
}

Вывод программы:

x = 10, y = 20
200

Что касается вопроса, появившегося в комментарии об объявлении параметр типа функции, тогда, например, C функция qsort использует такой параметр, который определяет отношение между двумя элементами массива.

void qsort(void *base, size_t nmemb, size_t size,
int compar(const void *, const void *));

Еще один пример Он использует тип функции в качестве аргумента шаблона для шаблона класса std::function.

...