ifstream as argument without reference

How can I pass an ifstream argument without reference?

1
2
3
4
5
6
7
8
9
10
11
  int main(void)
  {
    ifstream stream;
    foo(stream);
  }

  // where foo is:
  void foo(ifstream stream) // <-- (ifstream != ifstream &)
  {
     // do something with stream but don't affect main::stream
  }


The problem is that: "void foo(fstream) { /*...*/ }" is illegal
Last edited on
You cannot pass streams by value because streams are non-copyable. Why do you want to pass streams by value?
With a conforming implementation (not the GNU offering), we can move a std::ifstream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <fstream>
#include <utility>

void foo( std::ifstream stm )
{
    std::cout << stm.rdbuf() ;
}

int main()
{
    foo( std::ifstream(__FILE__) ) ;

    std::ifstream this_file(__FILE__) ;
    foo( std::move(this_file) ) ;
}
Last edited on
It seems OP wants to have two independent streams work on the same content (in this case the same file). @rodrigoloc why do you want this? It does't make much sense.
> It seems OP wants to have two independent streams work on the same content (in this case the same file).

It is only for input operations.
Just use two different std::ifstream objects; they don't interfere with each other.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <fstream>
#include <string>

void foo( const std::string& path_to_file )
{
   std::ifstream file(path_to_file) ;
   std::streamoff cnt = 0 ;
   char ch ;
   while( file.get(ch) ) if( ch == '\n' ) ++cnt ;
   std::cout << "*** from foo: " << cnt << " newlines ***\n" ;
}

int main()
{
    std::string path_to_file = __FILE__ ;
    std::ifstream file(path_to_file) ;
    std::string line ;

    for( int i = 0 ; i < 10 && std::getline(file,line) ; ++i )
        std::cout << line << '\n' ;

    std::cout << "\n-----------------------------\n" ;
    foo(path_to_file) ;
    std::cout << "-----------------------------\n" ;

    while( std::getline(file,line) ) std::cout << line << '\n' ;
}

http://coliru.stacked-crooked.com/a/df7fc9dfab76359b
I did something like JLBorges but using istream::tellg and istream::seekg. Like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void foo(string strFilename, streamoff nPosition)
{
    ifstream InFile(strFilename);
    InFile.seekg(nPosition);

    // do something...
}

int main(void)
{
    const string strFilename = "";
    ifstream InFile(strFilename);

    // do something...
     
    auto nPosition = InFile.tellg();
    foo(strFilename, nPosition);

    // do something else... and so on
     
     return 0;
}


But that doesn't work because ifstream::tellg returns negative numbers and they're diferent in every file I try.
> ifstream::tellg returns negative numbers

tellg() returns a negative value pos_type(-1) on failure.

Perhaps it would help if you post the actual code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ifstream InFile(strFilename);
if (InFile)
{
    // ...

    while (InFile)
    {
        string strCommand;
        InFile >> strCommand;

        if (strCommand == "this-is-a-string")
        {
            streampos nFilePosition = InFile.tellg();
            // nFilePositions gets negative values like -32 or -35

            foo(strFilename, nFilePosition);
        }

        InFile.ignore(UINT32_MAX, '\n');
    }

    InFile.close();
}
else
{
    // Throw exception
}
What does this print out?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    std::string strCommand;
    while( InFile >> strCommand )
    {
        if (strCommand == "this-is-a-string")
        {
            std::streampos nFilePosition = InFile.tellg();
            // nFilePositions gets negative values like -32 or -35

            std::streamoff offset = nFilePosition ;

            std::cout << offset << '\n' ;

            foo(strFilename, nFilePosition);
        }

        InFile.ignore(UINT32_MAX, '\n');
    }
That prints the same because streampos can be perfectly casted to streamoff.

But adding these two lines to the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ifstream InFile(strFilename);
if (InFile)
{
    // ...

    while (InFile)
    {
        string strCommand;

        cout << InFile.tellg() << endl; // <--
        InFile >> strCommand;
        cout << InFile.tellg() << endl; // <--

        if (strCommand == "this-is-a-string")
        {
            streampos nFilePosition = InFile.tellg();
            // nFilePositions gets negative values like -32 or -35

            foo(strFilename, nFilePosition);
        }

        InFile.ignore(UINT32_MAX, '\n');
    }

    InFile.close();
}
else
{
    // Throw exception
}


Prints something like this:
0
-35
2
3
21
27
42
43
Do not do this: cout << InFile.tellg() << endl;

std::fpos is not a simple numeric type that can be printed out as a number.
http://en.cppreference.com/w/cpp/io/fpos

If you want to find out what the offset is,
a. convert the streampos to a streamoff
b. streamoff is a signed integral type, it can be printed out as a meaningful number.


Also, verify that the stream is in a good state before tellg(); or you would get std::streampos(-1)
(which is not equal to a numeric value of -1; it represents an invalid position.)

1
2
3
4
5
6
7
if( InFile >> strCommand ) // if the read succeeded
{
    streampos nFilePosition = InFile.tellg();
    
    // print out offset from beginning
    std::cout << std::streamoff( nFilePosition ) << '\n' ;
}

Last edited on
It keeps printing the same.

 
cout << streamoff(InFile.tellg()) << endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <fstream>
#include <string>

/*
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
*/

int main()
{
    std::ifstream InFile( __FILE__ ) ;

    std::string strCommand;
    while( InFile >> strCommand )
    {
        if (strCommand == "this-is-a-string" )
        {
            std::streampos nFilePosition = InFile.tellg();

            std::streamoff offset = nFilePosition ;

            std::cout << offset << '\n' ;

            //foo(strFilename, nFilePosition);
        }

        InFile.ignore(1000, '\n');
    }
}

/*
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
this-is-a-string foo boo doo goo
*/

http://coliru.stacked-crooked.com/a/228a2a7adfbcfd91
Fixed!
Thank you. The error was that Blender's text export format wasn't compatible enough with Windows' text format.
Topic archived. No new replies allowed.