1

Many coders may be confused this code:

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

I would like to understand this code clearly, so the question is:

  1. Why is std::istreambuf_iterator<char>(ifs) enclosed in (, )?

  2. How to determinate this code if remove the brackets here? and

  3. How to determinate the code if we don't remove the brackets?

Thanks for your help.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    Does this answer your question? [A confusing detail about the Most Vexing Parse](https://stackoverflow.com/questions/7007817/a-confusing-detail-about-the-most-vexing-parse) – Kaldrr Feb 21 '20 at 10:42
  • @Kaldrr thx, but what I want to understand is about Internal mechanism. By the way, what's meaning of function declaration in a function block? –  Feb 21 '20 at 11:43

1 Answers1

0

In declarations declarators may be enclosed in parentheses.

Consider the following function declaration

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

This declaration declares a function with two parameters of the type int.

In a declaration names of identifiers may be omitted.

So you may write

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

This declaration in turn declares a function that accepts two parameters of the function type int().

So this construction

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

can be considered by the compiler as a declaration of a function that has the return type std::string and with the first parameter of the type std::istreambuf_iterator<char> and the identifier ifs and the second parameter with the function type istreambuf_iterator<char>().

To distinguish a declaration from an expression there are used either parentheses like

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

or braces

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

Here is a demonstration program that shows how can look declarators in parameter declarations.

#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 );
}

The program output is

x = 10, y = 20
200

As for the question appeared in a comment about declaration of a parameter of a function type then for example the C function qsort uses such a parameter that specifiers the relation between two elements of an array.

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

Another example is of using a function type as a template argument for a class template std::function.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thx, its easily to understand, but what's meaning of function declaration in a function block? Why does compiler treat it as a function declaration instead of a variable? Is there any useful place to declare a function in a function? –  Feb 21 '20 at 11:48
  • @GallenCalade As I mentioned the identifiers of declarators may be omitted if they are not used. So a function parameter that has a function type like for example int h() can be written like int() omitting the identifier h. Function types are very often used for example as template arguments of std::function. – Vlad from Moscow Feb 21 '20 at 11:50