使用流缓冲区直接使用?:运算符时出现C ++错误

时间:2011-02-26 15:37:29

标签: c++ c++11 iostream

当我尝试使用带有流缓冲区重定向的三元条件运算符(?:)时,gcc会生成'此处首先需要的合成方法'错误。有什么问题,以及如何纠正以下程序?

#include <fstream>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace std;
    cout << cin.rdbuf();    //OK
    ofstream("tmp.txt") << cin.rdbuf(); //OK

    int i=1;
    (i > 1 ? ofstream("tmp.txt") : cout) << cin.rdbuf(); //Compilation ERROR. Why?
    return 0;
}

使用gcc4.4编译:

...    
/usr/include/c++/4.4/bits/ios_base.h: In copy constructor ‘std::basic_ios<char,   std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’:  
/usr/include/c++/4.4/bits/ios_base.h:790: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private  
/usr/include/c++/4.4/iosfwd:47: error: within this context  
/usr/include/c++/4.4/iosfwd: In copy constructor ‘std::basic_ostream<char,   std::char_traits<char> >::basic_ostream(const std::basic_ostream<char,   std::char_traits<char> >&)’:  
/usr/include/c++/4.4/iosfwd:56: note: **synthesized method** ‘std::basic_ios<char,   std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’   **first required here**   
../item1_1.cpp: In function ‘int main(int, char**)’:  
../item1_1.cpp:12: note: synthesized method ‘std::basic_ostream<char,   std::char_traits<char> >::basic_ostream(const std::basic_ostream<char,   std::char_traits<char> >&)’ first required here   

3 个答案:

答案 0 :(得分:5)

这与我的clang版本编译好,我认为它可能是一个gcc bug。

根据我对该标准的解读,coutstd::ostream类型的左值ofstream("tmp.txt")是类型的右值 std::ofstream

cv-qualifiers std::ostream都没有std::ofstream的基类,所以条件运算符有效,结果是 rvalue 并且类型为std::ostream

没有隐含任何操作数的复制。

  

如果E1E2具有类类型,并且基础类类型相同或者一个是另一个的基类:E1可以转换为匹配{{1如果E2的类与T2的类相同,或者是T1的类的基类,则T2的cv-qualification与cv-qualification相同,或者比T1的cv资格更高的cv资格。如果应用了转换,则E1将更改为仍然引用原始源类对象(或其相应子对象)的类型T2的右值。 [注意:即没有复制。 ]

您正在使用的operator<<重载是std::ostream的成员,因此不需要将临时绑定到非const引用,可以在非const <上调用该成员< EM>右值

basic_ostream<charT,traits>&
    basic_ostream<charT,traits>::operator<< (basic_streambuf<charT,traits>* sb);

修改

请注意,这已在C ++ 0x中发生了变化。现在,如果条件表达式的结果是 rvalue ,则始终会生成临时副本。由于ostream类型的对象不可复制,因此您的代码在C ++ 0x中无效。

见这里:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#446

答案 1 :(得分:1)

您可以这样使用条件运算符:

#include <fstream>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace std;
    ofstream file("tmp.txt");
    int i=1;
    (i > 1 ? file : cout) << cin.rdbuf();
    return 0;
}

这在gcc 4.4.3上为我编译。

我知道,不是你要找的单行班车。

注意:正如Evan在评论中指出的那样,这将导致即使不需要也会创建文件。

答案 2 :(得分:0)

我可以在这里看到两种可能性:

  1. cout是ostream类型,另一个(临时)是ofstream,并且它们不能以任何方式相互转换
  2. 即使它们是可转换的,结果也是临时的右值,它不会绑定到运算符&lt;&lt;因为它需要nonconst左值参考。