Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing reference to istream

Tags:

c++

reference

I am trying to write my program so that it can process either StdIn or a file specified on the command line.

I'm doing this by trying to initialize a reference to an istream to either refer to cin or an ifstream, using a conditional.

(similar techniques are described here and here)

But when I try with ifstream, I seem to get an error that the basic_istream move-constructor is declared protected.

istream& refToCIN  ( cin );                      // This is OK
const istream& refToFile = ifstream(args[1]);    // This is OK

const istream& inStream ( FileIsProvided()? ifstream(args[1]) : cin );
// This causes error:
// std::basic_istream<char,std::char_traits<char>>::basic_istream' : 
// cannot access protected member declared in class std::basic_istream<char,std::char_traits<char>>

ProcessStream(inStream); // This could either be a file or cin

Can this be reasonably done this way? Is there a good alternative I'm overlooking?

like image 461
abelenky Avatar asked Jun 01 '16 19:06

abelenky


People also ask

How do you initialize a reference variable?

There are three steps to initializing a reference variable from scratch: declaring the reference variable; using the new operator to build an object and create a reference to the object; and. storing the reference in the variable.

Can we declare a reference variable without initializing it?

A reference can be declared without an initializer: When it is used in a parameter declaration. In the declaration of a return type for a function call. In the declaration of class member within its class declaration.


1 Answers

The problem with your code is following:

Your left-hand side of the ternary operator is a temporary (rvalue). However, your right hand-side is an lvalue (cin is an lvalue). As a result, compiler is trying to create a temporary out of cin, and fails because of copy constructor being not available.

As for the sultions - you can simply replace rdbuf() of cin with rdbuf() of your file, and use cin everywhere.


Here's the ultimate solution OP came up with:

ifstream file;
std::streambuf* old_cin_buf = cin.rdbuf(); // Store the old value
if (FileIsProvided())
{
    file.open(args[1]);
    old_cin_buf = cin.rdbuf(file.rdbuf()); // Replace the ReadBuffer on cin.
    // Store the previous value as well.
}
// Use cin for all operations now.  It will either use the File or StdIn as appropriate.
...
// Restore the original value, in case it was changed by using a file.
cin.rdbuf(old_cin_buf); // This is better be done before file object here goes out of scope
like image 94
SergeyA Avatar answered Oct 02 '22 15:10

SergeyA