ofstream in class - attempting to reference a deleted function - c++

I have seen this question: Attempting to reference a deleted function (VS2013) but it didn't provide me an answer.
I have a member variable in class which its type is ofstream and a constructor which contains string parameter:
class dogs
{
public:
ofstream dogsFile;
dogs(string location)
{
}
};
The following error appears:
Error 2 error C2280: 'std::basic_ofstream>::basic_ofstream(const std::basic_ofstream> &)' : attempting to reference a deleted function c:\users\pc\documents\visual studio 2013\projects\database\database\database.cpp 26 1 Database
I have tried this code again but instead of using string I used char*:
class dogs
{
public:
ofstream dogsFile;
dogs(char* location)
{
}
};
And the error disappeared. Why? why does string makes the error?
Edit:
This is the whole code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class dogs
{
ofstream dogsFile;
public:
dogs(string location)
{
}
};
int main(int argc, _TCHAR* argv[])
{
dogs dog = dogs("dog.bin");
return 1;
}

The original answer by Dieter seems to be correct.
I.e. This will compile:
dogs *dog = new dogs("dog.bin");
Your line will not, see his answer about copy constructors.
the dogs("dog.bin") will create an object then "=" will make a copy of it and give it to dog. Can't copy object with ofstream in it.
You can also fix this by using
dogs dog("dog.bin");
instead.

I can't think of this as anything else than a bug in VC++.
The way the dogs class is defined, the compiler should generate an implicit move constructor for it, which will call the move constructor for std::ofstream, which is defined as of C++11.
The rules for when to define an implicit move constructor are specified in the standard in [12.8/9] and [12.8/11]. They're also listed here. I can't see any reason not to declare the implicit move constructor in this case.
Then, the line
dogs dog = dogs("dog.bin");
must invoke a move from the temporary dogs object on the right hand side to the left-hand-side dog (the move may be elided, but the constructor needs to be accessible nonetheless).
In short, everything should work fine.
And it does in Clang 3.5. It doesn't work in GCC, but only because it doesn't have move constructors defined for stream classes (it's not standard-compliant in that respect).
Funnily enough, it works in VC++, as the OP duly mentioned, if the dogs constructor is declared to take anything else but a std::string by value. Change the constructor to any of the following:
dogs(const string& location)
or
dogs(int a) //And change the call accordingly, of course.
or
dogs(A a) //And change the call accordingly (A is a user-defined class).
and everything will work fine in VC++, as it should.
The fact that it doesn't work only for std::string passed by value seems to indicate there's a bug in the compiler. Basically, in that case, and only in that case, the compiler decides not to define the implicit move constructor, which causes the copy initialization to fall back to calling the copy constructor, which causes the error.
If you explicitly define the move constructor, like this:
dogs(dogs&& arg) : dogsFile(std::move(arg.dogsFile)) { }
again, everything works fine, including with the constructor taking a std::string by value.
I can't see any valid reason for VC++ to behave this way.

Related

C++ int pointer retroactively dereferences self

I've recently begun using C++ to try and program an Arduino library for a project I'm working on. In this library, I'm including another library published on GitHub, which I assume compiles on its own. As a part of the constructor for my class, I am creating and assigning an object of the published class. When I call the constructor, which takes two integers, with two integers, I get the following error:
Cell.cpp:7:31: error: no match for call to '(DS3904) (int&, int)'
_digipot(digipotAddress, 2);
^
EDIT: I was told by the comments before I edited this that a reference should work out just fine in this instance. Here is the library I am using. Following are the header file:
Cell.h:
#ifndef Cell_h
#define Cell_h
#include "Arduino.h"
#include "DS3904.h"
class Cell {
public:
Cell(int cellNumber, int digipotAddress, int resistorAddress);
void setCellVoltage(int voltage);
int getCellNumber();
private:
unsigned int _cellNo;
unsigned int _resistorAddress;
DS3904 _digipot;
};
#endif
And the actual C++ file, Cell.cpp (note that some unused functions are omitted from this one):
#include "Arduino.h"
#include "Cell.h"
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
_digipot(digipotAddress, 2);
_cellNo = cellNumber;
_resistorAddress = resistorAddress;
}
This actually doesn't have anything to do with pointers or references. You've got the wrong syntax for calling the constructor of the member object _digipot, and your code gets parsed as something different that results in a confusing error message.
You have a class Cell which has a member _digipot that is of type class DS3904. So your constructor for Cell needs to construct _digipot, but in C++, this isn't done by calling _digipot's constructor in the body of your Cell constructor. Instead it needs to be done in a member initializer list. So the correct way to write your constructor Cell::Cell would be:
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress)
: _digipot(digipotAddress, 2),
_cellNo(cellNumber),
_resistorAddress(resistorAddress)
{
// no code needed in the body
}
The idea is that in C++, there should never be any point in the program where you can see an object that exists but has not been fully constructed, with the one exception being that object's own constructor. If it was up to the body code of Cell::Cell to call _digipot's constructor, then it could also try to access _digipot before calling the constructor, at which point it would find it in an unconstructed state. So _digipot has to be constructed before the body of Cell::Cell starts execution, yet there still needs to be a way to specify which constructor of _digipot should be called, and with what arguments. Member initializer lists were invented to achieve this.
(You don't technically have to include the int members _cellNo and _resistorAddress in the member initializer list: if you leave them out, they get initialized to indeterminate values, and you can then assign to them in the body of the constructor like your existing code does. But it's cleaner to do everything in the member initializer list.)
So where did the weird error message come from? There are actually two error messages for your code, of which you only posted the second one, and the first one is the more informative one:
Cell-old.cpp: In constructor ‘Cell::Cell(int, int, int)’:
Cell-old.cpp:4:67: error: no matching function for call to ‘DS3904::DS3904()’
4 | Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
|
That's the first problem. You didn't specify a member initializer list, but _digipot still has to be constructed, so the default is for the object's default constructor to be called, i.e. a constructor taking no arguments. But class DS3904 doesn't have such a constructor, so this is an error.
The second issue is that your statement _digipot(digipotAddress, 2); in the body of the constructor isn't parsed as an attempt to call _digipot's constructor (after all, that should be impossible, since by the time we get here it should already have been constructed). Instead, a statement of the form obj(arg, arg) is applying the function call operator operator() to obj. If obj were a function or a function pointer, this would simply call the function, but this operator can also be overloaded for other types; see Why override operator()? for some examples of where this is useful.
So the compiler looks for an overloaded DS3904::operator() taking arguments compatible with what you've passed: an int lvalue, which could be passed as a reference (int&), and an int rvalue, which would have to be passed by value. No such overload exists, so this results in your second error.
By the way, clang's error messages on this code are a bit clearer:
Cell-old.cpp:4:7: error: constructor for 'Cell' must explicitly initialize the member '_digipot' which does not have a default constructor
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
^
./Cell.h:15:16: note: member is declared here
DS3904 _digipot;
^
./DS3904.h:27:7: note: 'DS3904' declared here
class DS3904
^
Cell-old.cpp:5:5: error: type 'DS3904' does not provide a call operator
_digipot(digipotAddress, 2);
^~~~~~~~
When faced with a confusing error message, it's often helpful to try a different compiler, and see if it can give you something more useful.

How to fix 'attempting to reference a deleted function' when the compiler implicitly deleted it

I am trying to make a generic class that can represent any object in its most base form, bits. To do this I created a Union of an array of chars (essentially bytes) and the object that the characters make up. Unfortunately when building, I get a strange warning and error for my union.
Warning: "The destructor was implicitly defined as deleted."
Error: "Attempting to reference a deleted function."
(both occur on the line following the definition of my union)
I know that you can create custom destructors for structs, classes and unions, but there is not a need to if you are not freeing up dynamic memory, correct? Yet somehow a destructor I never defined is being automatically called and the compiler deleted it implicitly. Hence the error.
The next thing I attempted was defining a destructor within my union; it did nothing because I never asked the os for additional memory. It was once again deleted. I needed to figure out why the compiler was deleting my function and then causing an error when trying to call it after it deleted it.
I attempted looking for this error in the Microsoft visual studio list, and what it came up with was that not making the constructor public would cause this error. Additionally, looking online here I found that oftentimes the copy constructor is what causes an error because it was never defined. So i tested it by creating a class of my own and using the copy constructor = on it. It worked just fine, but gave me the same error when attempting to use it with my typeAsChar class. Interestingly enough, this error is not called when I use my class with the C default structs, int, double, etc.
Here is the code that causes the issue.
template <class type>
union typeAsChar
{
type obj;
char arr[sizeof(type)];
};
template <class type>
class wontWork
{
public:
wontWork() {/* Do nothing, no data entered */}
wontWork(const type& obj) { foo.obj = obj; }
~wontWork() {/* When this goes out of scope, the default
destructor of the member 'type' should be called */}
typeAsChar<type> foo;
};
int main()
{
double testNum = 12345;
std::string testStr = "Hello World\n";
wontWork<std::string> test1(testStr); // has error
std::cout << test1.foo.obj;
wontWork<double> test2(testNum); // No error
std::cout << test2.foo.obj;
return 0;
}
Oddly enough, this compiles and runs perfectly with wontWork<std::string> commented out, but fails when my class is made with an object of anything other than the standard c structs (int, double, etc). Any clarification on the matter would be much appreciated.
Here is the answer by #Miles Budnek that worked perfectly. Thanks a lot for your info, I never knew that was a functionality in c++.
"reinterpret_cast(&object) is a well-defined way to access the bytes that make up an object (even if it's not very useful for something like std::string). Type-punning via union is not well-defined. – Miles Budnek"

C++ Primer questions: delegates to a default constructor

It was careless of me to make such a wrong guess. I did a lot of useless works because I ignored the line where the default constructor is declared on the book. Sorry about that.
=============contents below is the original question=================
I have a question about an example & explanation at C++ Primer 5th, P.292, it is about how to use delegate constructors:
class Sales_data {
public:
//target constructor
Sales_data(std::string s, unsigned cnt, double price) :
bookNo(s), units_sold(cnt), revenue(cnt * price) { }
//delegate constructor that I have question on
Sales_data(std::istream &is): Sales_data() {read(is, *this)}
};
for explaining how this delegate constructor works,the book said:
It delegates to the default constructor , which in turn delegates to the three-argument constructor.
I was confusing about the explanation. I don't get why the delegate constructor delegates a default constructor first , then still need to delegates the target constructor.
For confirming my thought I did some experiments:
First, I have a thought that the target constructor will automatically generate a default constructor, because there is no default constructor declaration in the example code; And I know the default constructor is a must when I have my custom constructor. So I tried to compile the class with some simple test code here:
int main(int argc, char const *argv[]) {
Sale_data item1(std::cin);
print(std::cout, item1);
return 0;
}
and I got a error:
error: no matching function for call to Sale_data::Sale_data()
Then I added the Sales_data() = default, the program printed the correct result.
Next, I deleted my target constructor. However, the program still represents a same result as what I got from the step 2: looks like the default constructor did its job well.
Comparing with what the book explained, my experiment shows that the target constructor has no business with the delegate constructor, in my case. Would you please point out where am I wrong??
Thanks in Advance for your help!
First, I have a thought that the target constructor will automatically
generate a default constructor, because there is no default
constructor declaration in the example code;
There is a default constructor in the book. Just right after the three parameter target consturctor. Did you refer to the wrong code sample?
Sales_data(): Sales_data("", 0, 0) {}

Construct object by calling constructor (method) explicitly

Definition of class:
#pragma once
#include <string>
#include <utility>
namespace impress_errors {
#define BUFSIZE 512
class Error {
public:
Error(int number);
Error(std::string message);
Error(const char *message);
bool IsSystemError();
std::string GetErrorDescription();
private:
std::pair <int, std::string> error;
char stringerror[BUFSIZE]; // Buffer for string describing error
bool syserror;
};
} // namespace impres_errors
I have some piece of code in file posix_lib.cpp:
int pos_close(int fd)
{
int ret;
if ((ret = close(fd)) < 0) {
char err_msg[4096];
int err_code = errno;
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
}
return ret;
}
And in another file fs_creation.cpp:
int FSCreation::GenerateFS() {
int result;
try {
result = ImprDoMakeTree(); //This call pos_close inside.
}
catch (impress_errors::Error error) {
logger.LogERROR(error.GetErrorDescription());
return ID_FSCREATE_MAKE_TREE_ERROR;
}
catch (...) {
logger.LogERROR("Unexpected error in IMPRESSIONS MODULE");
return ID_FSCREATE_MAKE_TREE_ERROR;
}
if(result == EXIT_FAILURE) {
return ID_FSCREATE_MAKE_TREE_ERROR;
}
return ID_SUCCESS;
}
On my version of compiler this one is compiled and work correct:
g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 (Ubuntu Maverick - 10.04)
On another version of compiler:
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 (Ubuntu Narwhal - 11.04) it causes
error:
posix_lib.cpp: In function ‘int pos_close(int)’:
posix_lib.cpp:363:46: error: cannot call constructor ‘impress_errors::Error::Error’ directly
posix_lib.cpp:363:46: error: for a function-style cast, remove the redundant ‘::Error’
Questions:
1. Why this work on one version of g++, and failed on another?
2. What happens when I explicitly call constructor for creating object? Is it correct?
And why this is working?
You are not calling the constructor (well, you are, but not in the way you mean it). The syntax ClassName(constructor params) means to create a temporary object of the type ClassName, using the given parameters for its constructor. So you aren't simply calling the constructor; you are creating an object.
So you are creating an Error object. Your problem is that the name of Error is impress_errors::Error, not "impress_errors::Error::Error". The second ::Error would seem to be an attempt to name the constructor. Constructors don't have names; they are not functions that you can find and call at your whim (again, not in the way you mean it).
This looks like an error in the compiler which rejects it. The code is
legal, but not for the reasons you think. There is no such thing as
"calling constructor (method) explicitly", because constructors don't
have names (§12.1/1). On the other hand, impress_errors::Error::Error
is the name of a type; class name injection (§9/2) means that the class
impress_errors::Error contains a declaration of the name Error in
the class, as a synonym for the name outside of the class. So
impress_errors::Error, impress_errors::Error::Error,
impress_errors::Error::Error::Error, etc. all name the same type
(although only the first is idiomatic—the rest are all just extra
noise). And when the name of a type is followed by a parenthesized
expression list, as is the case here, it is an "Explicity type
conversion (functional notation)". (§5.2.3—and the standard says it
is an explicit type conversion even if the expression list is empty, or
contains more than one expression—don't ask me what "type" is
being converted in such cases.) So impress_errors::Error(err_code) (or
impress_errors::Error::Error(err_code) means convert err_code into
an impress_errors::Error. Which, in this case, will result in calling
the constructor, since that's the only way to convert an int into an
impress_errors::Error. (It's possible, however, to construct cases
where the compiler will call a user defined conversion function on the
object being converted.)
It should be ok if You do what compiler is asking You. Just remove one "Error" statement;> I'm not sure why this changed in gcc, but class_name::construction_name is just redundant. Compiler knows that You want to call constructor, because its name is the same as the name of the class
While you could explicitly call the constructor using placement new, see placement operators, you don't have an object or piece of memory in which to place the object yet. Probably easier to use something like
throw new MyError(MyParams);
and make the exception handler responsible for deleting it. FWIW Microsoft use this approach with MFC.
I ran into the exact same error message.
The solution is to change this line:
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
to
throw impress_errors::Error(err_code); //Call constructor explicitly
In C++ you can call the base class constructor inside a derived class constructor, just never use the scope resolution operator ::

const to non-const c++

is this possible:
changing a constant variable to non-constant
I am making a whole new string class and my constructor looks like this
LString(const char string1[]) {/* whatever I do */}
I wouldn't put the const keyword but that is the only way I can get strings like
LString ls = "a string";
I will have a lot of functions to modify this string
even though I make a copy of this string I still cannot convert const to non const
is it possible
if not, can anyone think of a loophole
ok so some people were saying that there is no problem, well here is my code
#include <iostream>
#include <cstdlib>
using namespace std;
class LString
{
public:
LString(const char string1[]){
char s1[250] = {string1};
cout << "you constructed LString with a const string as a parameter";
}
};
this comes up with the following errors
file.cpp: In constructor 'LString::LString(const char*)':
file.cpp:7:24: error: invalid conversion from 'const char*' to 'char'
if this makes a difference I am using the mingw compiler without an IDE
I am compiling through the command prompt
I think thats all the info you might need
tell me if you need anymore
Your constructor is fine - the input should be const.
The copy can be non-const, no problem.
#include <string.h>
class A {
public:
A(const char* string)
: a(strdup(string))
{}
char* a;
};
Here I'm using strdup to make a copy. What are you using?
I believe the compiler thinks you're trying to change the string you're assigning from. Since it can't be changed that's why it's complaining. Did you make a copy of the string to make changes to?
I don't see the problem. Keep the constructor signature as it is, but make the internal variable non-const and copy it over. Copy it at the start of the func and then work with that variable instead.