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:
Why is std::istreambuf_iterator<char>(ifs)
enclosed in (
, )
?
How to determinate this code if remove the brackets here? and
How to determinate the code if we don't remove the brackets?
Thanks for your help.
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
.