Temporary non-const istream reference in constructor (C++)

耗尽温柔 提交于 2020-01-15 11:02:09

问题


It seems that a constructor that takes a non-const reference to an istream cannot be constructed with a temporary value in C++.

#include <iostream>
#include <sstream>

using namespace std;

class Bar
{
public:
   explicit Bar(std::istream& is) {}
};

int main()
{
   istringstream stream1("bar1");
   Bar bar1(stream1); // OK on all platforms

   // compile error on linux, Mac gcc; OK on Windows MSVC
   Bar bar2(istringstream("bar2"));

   return 0;
}

This compiles fine with MSVC, but not with gcc. Using gcc I get a compile error:

g++     test.cpp   -o test
test.cpp: In function ‘int main()’:
test.cpp:18: error: no matching function for call to ‘Bar::Bar(std::istringstream)’
test.cpp:9: note: candidates are: Bar::Bar(std::istream&)
test.cpp:7: note:                 Bar::Bar(const Bar&)

Is there something philosophically wrong with the second way (bar2) of constructing a Bar object? It looks nicer to me, and does not require that stream1 variable that is only needed for a moment.

EDIT: In response to Johannes Schaub's comment I'd like to give a bit more context. First, this is not the first time I have been annoyed by this behavior of C++, so I am genuinely interested in the higher level philosophical discussion of this issue. That said, in this particular case I have a class that reads in a file that contains data used to construct the object. I also like to write automated tests that use a string instead of the file. But using the file for construction is the primary use case. So I decided to make a constructor that takes an istream, so I could use either a file(stream), or a string(stream). That is how I got here. My test programs construct objects directly from strings, to simulate reading files. This saves me the trouble of creating separate data files for each little test.


回答1:


This is just how C++ works currently: you cannot bind non-const references to temporary objects. MSVC is non-standard in allowing this.

C++0x will have r-value references and change things around a bit here. There are various philosophical interpretations people have tried to apply—for both sides of the issue—but I haven't found one that is wholly convincing. It seems more of "you just have to pick one behavior and stick to it", which explains both current C++ and 0x's changes: the chosen behavior has shifted.




回答2:


Roger is right… this is a generic policy of C++ that only const references may bind to temporaries. I don't think rvalue references would help you, though, because in the case of passing a non-temporary stream you do want to continue using its modified state.

More to the point, why not replace the constructor with a friend extractor istream &operator>>(istream &s, Bar &b)? At the cost of adding an uninitialized state to the object, the syntax would be even more C++-ish.



来源:https://stackoverflow.com/questions/2405871/temporary-non-const-istream-reference-in-constructor-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!