从std :: istreambuf_iterator创建std :: string,奇怪的语法怪癖

时间:2014-08-27 01:06:29

标签: c++ stl

我找到了以下用于将文件读入字符串的习惯用法:

std::ifstream file("path/to/some/file.ext");
std::string contents(
    std::istreambuf_iterator<char>(file),
    (std::istreambuf_iterator<char>())
);

它的效果很好。但是,如果我删除第二个迭代器参数周围的括号,那就是:

std::string contents(
    std::istreambuf_iterator<char>(file),
    std::istreambuf_iterator<char>()
);

一旦我尝试在字符串对象上调用任何方法,例如:

const char *buffer = contents.c_str();

我收到表单的编译错误:

error: request for member 'c_str' in 'contents', which is of non-class type 'std::string(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)()) {aka std::basic_string<char>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)())}'

此外,如果我尝试将该字符串分配给另一个字符串:

std::string contents2 = contents;

我收到表单错误:

error: conversion from 'std::string(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)()) {aka std::basic_string<char>(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)())}' to non-scalar type 'std::string {aka std::basic_string<char>}' requested

这是为什么?我看不出需要这些括号的原因,更不用说影响contents变量的类型定义了。我正在使用g ++ 4.8.2。

1 个答案:

答案 0 :(得分:16)

这是Most Vexing Parse的一个例子:

std::string contents(
    std::istreambuf_iterator<char>(file),
    std::istreambuf_iterator<char>()
);

该语句被解析为带有两个参数的名为contents的函数的声明。一个参数是名为file的{​​{1}}类型的变量,第二个参数是一个不带参数并返回std::istreambuf_iterator的函数。功能参数名称的规范是可选的。

在括号中包含至少一个表达式会导致它被解析为变量定义。

C ++ 11通过提供 uniform-initialization 来解决这个问题:

std::istreambuf_iterator