为什么`std::istreambuf_iterator<char>`在构造字符串时被视为函数声明?

why is `std::istreambuf_iterator<char>` regard as function declaration when constrcuting a string?

很多coder可能会混淆这段代码:

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. 不去掉括号怎么判断编码?

感谢您的帮助。

在声明中,声明符可以用括号括起来。

考虑以下函数声明

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

这个声明声明了一个带有两个 int 类型参数的函数。

标识符的声明名称可以省略。

所以你可以写

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

这个声明又声明了一个接受两个函数类型参数的函数int()

所以这个构造

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

可以被编译器视为具有 return 类型 std::string 且具有类型 std::istreambuf_iterator<char> 和标识符 [=20] 的第一个参数的函数声明=] 和函数类型为 istreambuf_iterator<char>().

的第二个参数

为了区分声明和表达式,使用了括号,如

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 *));

另一个示例是使用函数类型作为 class 模板 std::function.

的模板参数