I can’t seem to open a file without storing it in a variable. I can do this:
ifstream blob("somefile");
string line;
blob >> line;
But when I try this:
string line;
ifstream("somefile") >> line;
The compiler (clang) gives this error:
t.cpp:7:23: error: invalid operands to binary expression ('ifstream' (aka 'basic_ifstream<char>') and 'string' (aka 'basic_string<char>'))
ifstream("thing") >> i;
~~~~~~~~~~~~~~~~~ ^ ~
In file included from t.cpp:1:
In file included from /usr/include/c++/4.6/iostream:39:
In file included from /usr/include/c++/4.6/ostream:39:
In file included from /usr/include/c++/4.6/ios:42:
In file included from /usr/include/c++/4.6/bits/ios_base.h:42:
In file included from /usr/include/c++/4.6/bits/locale_classes.h:41:
In file included from /usr/include/c++/4.6/string:53:
/usr/include/c++/4.6/bits/basic_string.h:2679:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>] not
viable: no known conversion from 'ifstream' (aka 'basic_ifstream<char>') to 'basic_istream<char> &' for 1st argument
operator>>(basic_istream<char>& __is, basic_string<char>& __str);
^
In file included from t.cpp:1:
In file included from /usr/include/c++/4.6/iostream:40:
/ usr/include/c++/4.6/istream:121:7: note: candidate function not viable: no known conversion from 'string' (aka 'basic_string<char>') to
'__istream_type &(*)(__istream_type &)' for 1st argument
operator>>(__istream_type& (*__pf)(__istream_type&))
^
/usr/include/c++/4.6/istream:125:7: note: candidate function not viable: no known conversion
... a few more hundred pages of crap ...
1 error generated.
So, what’s the difference between the two? With other classes, calling it directly works just fine. Is there some template magic involved that makes it ambiguous?
The code that you post is not valid in C++03 (i.e., what was the C++ language standard until September 2011). In C++03, there is only one overload of
operator>>that might be considered here [I’ve removed all of the template code because it is not relevant]:Note that the
std::istreamparameter is a non-const reference, so a temporarystd::istreamobject cannot be used. In your code, you are trying to use a temporary object there.In C++11 (i.e., the current C++ language standard), there is an additional overload which takes the
std::istreamobject by rvalue reference. This allows either a temporary to be passed via that parameter.Visual C++ already supports this feature of C++11, which is why, as Benjamin Lindley points out in a comment, your code will indeed compile if you use Visual C++ 2010 or later. Your build of Clang may support this if you use the -std=c++0x flag.