我找到了以下用于将文件读入字符串的习惯用法:
std::ifstream file("path/to/some/file.ext");
std::string contents(
std::istreambuf_iterator<char>(file),
(std::istreambuf_iterator<char>())
);
Run Code Online (Sandbox Code Playgroud)
哪个工作得很好.但是,如果我删除第二个迭代器参数周围的括号,那就是:
std::string contents(
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()
);
Run Code Online (Sandbox Code Playgroud)
一旦我尝试在字符串对象上调用任何方法,例如:
const char *buffer = contents.c_str();
Run Code Online (Sandbox Code Playgroud)
我收到表单的编译错误:
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;
Run Code Online (Sandbox Code Playgroud)
我收到表单错误:
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.
0x4*_*2D2 17
这是Most Vexing Parse的一个例子:
std::string contents(
std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()
);
Run Code Online (Sandbox Code Playgroud)
该语句被解析为带有contents两个参数的函数的声明.一个参数是一个名为filetype 的变量,另一个参数是一个std::istreambuf_iterator不带参数并返回一个的函数std::istreambuf_iterator.功能参数名称的规范是可选的.
在括号中包含至少一个表达式会使其被解析为变量定义.
C++ 11通过提供统一初始化解决了这个问题:
std::string contents{std::istreambuf_iterator<char>{file}, {}};
Run Code Online (Sandbox Code Playgroud)