Troubles using fstream in a class - c++

I get the following error, when compiling:
1>c:\users\ra\source\repos\sandbox\game\gamesetup_1\gamesetup_1\main.cpp(15): error C2280: 'DebugLib::DebugLib(const DebugLib &)': attempting to reference a deleted function
1>c:\users\ra\source\commonincludes\tannic\debuglib\debuglib.h(41): note: compiler has generated 'DebugLib::DebugLib' here
1>c:\users\ra\source\commonincludes\tannic\debuglib\debuglib.h(41): note: 'DebugLib::DebugLib(const DebugLib &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)'
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.16.27023\include\fstream(1421): note: 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)': function was explicitly deleted
1>Done building project "GameSetup_1.vcxproj" -- FAILED.
The code looks like this:
DebugLib.h:
#include <string>
#include <fstream>
class DebugLib
{
public:
DebugLib(); // Reset timestamp etc.
~DebugLib(); // Flush output buffer
void Init(uint8_t output, std::string fileName = "debug.log"); // Initializes Log
void Log(int category, std::string msg); // Add a line to the log
void Flush(); // Output the remains of the Debug buffer
void Shutdown(); // Shut it down
private:
unsigned int m_initTime;
unsigned int m_bufferPos;
std::string m_outputBuffer[DEBUG_MAXSIZE];
std::fstream m_fileStream;
uint8_t m_output;
bool m_running;
};
main.cpp:
#include <iostream>
#include <DebugLib.h>
using namespace std;
int main()
{
DebugLib gDebugger = DebugLib();
gDebugger.Init(DEBUG_LOG_TO_SCREEN);
cout << "Running!" << endl;
gDebugger.Shutdown();
cin.get();
return 0;
}
As soon as I declare m_fileStream I get the error. Do I have a wrong declaration ?
When I remove all the use of m_fileStream in DebugLib.cpp, the code compiles fine, and runs (but of course not as attended)

I couldn't find a duplicate even though I've seen this asked before, so:
Let's start by explaining the error messages. I'll ignore the line numbers and error codes, as those are rarely useful until after you've understood (or at least read) the rest of the error message.
'DebugLib::DebugLib(const DebugLib &)': attempting to reference a deleted function
This is the main error: an attempt to use a function that is deleted, namely the copy constructor for DebugLib. Since you did not explicitly specify a copy constructor, it is up to the compiler to define one for you. The compiler will define a naive copy if possible. If this definition is not possible, it will delete the copy constructor for you.
As you noticed, the compiler is able to define a naive copy until you add a field that cannot be copied (such as std::fstream).
note: compiler has generated 'DebugLib::DebugLib' here
This is a clarifying note that helps the error refer to two lines in your program. The line number that came with the main error message is where you tried to do the copy, and the line number that comes with this note is where the copy constructor is generated. The compiler is trying to be helpful because it doesn't know which location you'll want to change to address this error.
note: 'DebugLib::DebugLib(const DebugLib &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)'
This note explains the thing you noticed: copying your class is prevented because the std::fstream member cannot be copied. This message uses the name basic_fstream at this point, so it helps to know that fstream is an instantiation of the basic_fstream template. So that mess of code at the end of this note just names the copy constructor of std::fstream.
note: 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)': function was explicitly deleted
This is a further clarification. The line before this said "deleted or inaccessible". This line clarifies that to "explicitly deleted".
Now that we have read the error, we can go look at the lines to which it refers. The troublesome line is
DebugLib gDebugger = DebugLib();
This line requests that a DebugLib object be default constructed then copied to gDebugger. And there's the problem: it cannot be copied! The solution is to simplify your logic by removing the copy. You can invoked the default constructor directly on gDebugger. (This works for other constructors as well, should your code need them.)
DebugLib gDebugger{};
As a bonus, your code is shorter.

Related

Unit testing a vector string

I have this really simple line of code in my production-code(A.cpp) as follows:
std::string A::getString(int i) {
return sVect_[i];
}
with the header as follows:
class A{
public:
std::string getString(int i);
...
private:
vector<std::string> sVect_;
...
};
I've been trying to test the getString() function using googletest but an error keeps popping out:
error: invalid conversion from 'char* (*)(const char*, int)throw ()' to 'int'
error: initializing argument 1 of 'std::string A::getString(i)'
This was my test program:
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i));
}
I couldn't quite grasp the workaround of the vector string and how to call it in my test program without ever changing the production code. I even use the hack, adding #define statements, to access the private member but still couldn't do it.
How do my test actually looks like to successfully call that function?
Note: I'm on Linux and using gcc. Thank you in advance guys.
Perhaps the error message is misleading. Have you defined i globally somewhere else? To me it looks like in the local scope because it does not know what the value of the variable i is, it is misbehaving in an unexpected way
TEST(ATest, getString){
A a;
EXPECT_EQ("c", a.getString(i)); //here what is the 'i' and where is it defined
}

error: expected primary-expression before ')' token (C)

I am trying to call a function named characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne sel) which returns a void
This is the .h of the function I try to call:
struct SelectionneNonSelectionne;
void characterSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
void resetSelection(SDL_Surface *screen, struct SelectionneNonSelectionne);
On my main function, I try to call it like this:
characterSelection(screen, SelectionneNonSelectionne);
When I compile, I have the message:
error: expected primary-expression before ')' token
I made the includes. I suppose I miscall the second argument, my struct. But, I can't find why on the net.
Have you got any idea about what I did wrong?
You should create a variable of the type SelectionneNonSelectionne.
struct SelectionneNonSelectionne var;
After that pass that variable to the function like
characterSelection(screen, var);
The error is caused since you are passing the type name SelectionneNonSelectionne
A function call needs to be performed with objects. You are doing the equivalent of this:
// function declaration/definition
void foo(int) {}
// function call
foo(int); // wat!??
i.e. passing a type where an object is required. This makes no sense in C or C++. You need to be doing
int i = 42;
foo(i);
or
foo(42);
You're passing a type as an argument, not an object. You need to do characterSelection(screen, test); where test is of type SelectionneNonSelectionne.
I seen this problem with the latest nightly build of Code::Blocks. When I switched back to the stable release of Code::Blocks, 20.03 at the time of this writing, the problem went away and my code compiled and ran without problems. I'm not sure what Code::Blocks is doing, but it is very annoying. I got this repeatedly on a C++ project for every NULL in my code, forcing me to use nullptr instead.

Can't declare ifstream class member in header file

I am trying to declare an ifstream object in a header file as is shown but I get an error saying that it cannot be accessed. I have tried various things such as making it into a pointer instead, initialising in the .c file etc. but my code can't seem to get part the declaration of it.
ReadFile.h:
#ifndef READFILE_H
#define READFILE_H
#include "cv.h"
#include "highgui.h"
#include <iostream>
#include <fstream>
class ReadFile{
private:
std::ifstream stream;
public:
std::string read();
ReadFile(); // Default constructor
~ReadFile(); // Destructor
};
#endif
ReadFile.c:
#include "ReadFile.h"
ReadFile::ReadFile(){
stream.open("./data.txt");
}
ReadFile::~ReadFile(){
stream.close();
}
The error that I am getting is:
Error 9 error C2248: 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream' : cannot access private member declared in class 'std::basic_ifstream<_Elem,_Traits>' c:\users\Bob\documents\project\models\readfile.h 23 1 Project
The output is:
1>c:\users\Bob\documents\project\models\readfile.h(23): error C2248: 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream' : cannot access private member declared in class 'std::basic_ifstream<_Elem,_Traits>'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\fstream(827) : see declaration of 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> This diagnostic occurred in the compiler generated function 'ReadFile::ReadFile(const ReadFile &)'
The error occurs when std::ifstream stream; is included and will disappear when this line is removed. What could be causing this error? Have I missed something really obvious or is there more to it?
The problem is that std::ifstream doesn't have a public copy constructor (because copying one wouldn't make sense) but the compiler-generated copy constructor for your class wants to use it.
It doesn't have any available assignment operator for the same reason (i.e. copying a std::ifstream is nonsense).
You should disallow copying and assignment for your class as well.
A simple way is to add
private:
ReadFile(const ReadFile&);
ReadFile& operator=(const ReadFile&);
to your class, if you're using C++03.
In C++11, use the = delete syntax.
public:
ReadFile(const ReadFile&) = delete;
ReadFile& operator=(const ReadFile&) = delete;
This isn't an answer per se, but in case anyone comes across this question in the future after struggling as much as I just have, I decided to post it anyway.
I was facing a very similar issue to the OP for basically the same reason, although the error message that Visual C++ was giving me was 'ClassName::ClassName(const ClassName &)': attempting to reference a deleted function. In my inexperienced mind, I was thinking "WTF, I'm not copying or assigning any copies anywhere!".
However, after an hour of screaming at the computer in frustration I was able to narrow the problem down to the ifstream class member, which led me here. And thanks to the accepted answer, I was able to narrow the problem down even further to this single line of code:
list.emplace_back(objParam);
Little did I know that std::vector objects need a copy constructor defined on their template parameter's type in order to reserve space for future emplace_back() calls and the like!
So the solution comes from this SO answer courtesy of Bryan Chen (emphasis added by me):
So you can see emplace_back does use the desired constructor to create the element and call copy constructor when it need to grow the storage. You can call reserve with enough capacity upfront to avoid the need to call copy constructor.
Full credit and many thanks go to Bryan and molbdnilo for leading me to this discovery.

How do I use an std::fstream from within a block?

I'm having trouble trying to use an ifstream from within a block. (This is part of a larger, complex project, so I whipped up a quick little source file with just the relevant parts.)
// foo.cpp, in its entirety:
#include <iostream>
#include <fstream>
#include <Block.h>
int main() {
__block std::ifstream file("/tmp/bar") ;
// ^ tried this with and without the __block
void (^block)() = ^{
file.rdbuf() ;
file.close() ;
file.open("/tmp/bar") ;
} ;
block() ;
}
If I declare the ifstream with __block, I get:
foo.cpp:6:24: error: call to implicitly-deleted copy constructor of
'std::ifstream' (aka 'basic_ifstream<char>')
__block std::ifstream file("/tmp/bar") ;
^~~~
If I declare it without __block, I get:
foo.cpp:8:3: error: call to implicitly-deleted copy constructor of
'const std::ifstream' (aka 'const basic_ifstream<char>')
file.rdbuf() ;
^~~~
// rdbuf() and (presumably) other const functions
foo.cpp:9:3: error: member function 'close' not viable: 'this' argument has
type 'const std::ifstream' (aka 'const basic_ifstream<char>'), but
function is not marked const
file.close() ;
^~~~
// open(), close(), and (presumably) other non-const functions
What's the proper way to use fstreams inside of blocks?
From Block Implementation Specification
It is an error if a stack based C++ object is used within a block if it does not have a copy constructor.
Which is the first error - ifstream blocks copy. __block requires copy.
As the quote says, one option is to declare ifstream on heap(new/delete).. but that is messy.
The rest of the errors are simple const correctness errors. Not declaring __block imports the objects as a const copy, which is the first of the two errors, and it cannot be used to call non const functions like close.
Try to switch to lamda expressions from C++11 and see if they alleviate these issues.

Passing fstream reference as function parameter in C++11

I've just encountered an problem today: The following code seems to work in MSVC++ 2010 but not with Clang LLVM 4.1 (with GNU++11).
#include <fstream>
void foo(std::fstream& file){
file << "foo";
}
int main() {
std::fstream dummy("dummy");
foo(dummy);
return 0;
}
generates
Invalid operands to binary expression (std::fstream (aka basic_fstream<char>) and const char[4])
on Clang. I thought passing iostream arguments by reference would be common practice in C++. I'm not even sure if this is related to clang, C++11 or anything else.
Any idea how I can pass streams to functions then?
I assume that your original code (that you only partially posted in your original question) looked something like this:
#include <iosfwd>
void foo(std::fstream& file){
file << "foo";
}
int main() {
std::fstream dummy("dummy");
foo(dummy);
return 0;
}
Indeed, this gives the following error message with clang++ 3.2
Compilation finished with errors:
source.cpp:4:10: error: invalid operands to binary expression ('std::fstream' (aka 'basic_fstream<char>') and 'const char [4]')
file << "foo";
~~~~ ^ ~~~~~
source.cpp:8:17: error: implicit instantiation of undefined template 'std::basic_fstream<char, std::char_traits<char> >'
std::fstream dummy("dummy");
^
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/iosfwd:118:11: note: template is declared here
class basic_fstream;
^
2 errors generated.
Unfortunately, you only posted the first error message but not the second.
From the second error message, it is obvious that you only #include <iosfwd> but not #include <fstream>. If you fix that, everything will be OK.
Please post both the complete code and all the error messages next time.