Construct object by calling constructor (method) explicitly - c++

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 ::

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"

Default argument allowing constructor to call private method

I have the class
class A
{
public:
class Key
{
Key() {}
Key(Key const &) {}
};
A(Key key, int a = 5) {}
};
The constructor for Key is private, so no one should be able to construct an object A. However, with the following code:
int main() {
A a(A::Key()); // this compiles !!!
A a2(A::Key(), 5); // this doesn't
// somehow defaulting the argument causes the private constructor
// to be OK - no idea why
return 0;
}
By making use of the default argument for int a in my constructor, the compiler happily compiles my usage of A::Key() despite the fact that it is private. If I explicitly give a value for a, though, the compiler correctly recognizes that I am trying to use a private constructor and errors out. Why is this? Is there someway to force the compiler to error out for the first example as well?
See here for live example.
This is because of the most vexing parse.
A a(A::Key());
Does not create a A named a and construct it with a temporary A::Key. It creates a function a that returns an A and takes an unnamed pointer to function that returns a A::Key.
If you add a pair of parentheses to it you will get a compiler error
A a((A::Key()));
That you are trying to call a private constructor. Alternatively you can use uniformed initialization which also disambiguate it and will cause a compile error
A a(A::Key{});

ofstream in class - attempting to reference a deleted function

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.

Preventing construction by throwing exception before constructor body

C++
I want a class to throw an exception before its constructor's body's opening curly brace { by using its own member function to prevent construction. I defined a member function, whose purpose is only to unconditionally throw an exception, with an arbitrarily chosen non-void return type and a dummy data member whose type matches that return type, so that I can trigger the throw by constructing this data member with a call to said member function in the constructor initializer list. This works but isn’t elegant because in a non-toy class, the dummy variable would serve no other purpose but to have an excuse for the member function to run, and the member function’s non-void return type serves no other purpose but to have an excuse for it to be callable by the constructor of the dummy data member of the same type.
This toy compiles but isn’t elegant:
class Toy
{
public:
Toy() : dummy(preventer()) {}
private:
int dummy;
int preventer() {throw -1; return 0;}
};
#include <iostream>
int main()
{
try
{
Toy t;
}
catch (const int& e)
{
std::cout << "caught the exception\n";
}
return 0;
}
Console Output:
caught the exception
Without the dummy variable, is there a way to throw an exception before the opening curly brace { of the constructor body?
Yes you can use a base class instead of a data member, and then invoking the base class' constructor.
Note that old versions of the GNU debugger gdb (some years ago) was unable to break on such exception.
However, works OK with Visual C++, and I believe also with modern versions of the GNU toolchain.
You can avoid the dummy return value of the function like this:
bool called = (function(), true);
The comma-operator in between the two expressions on the right evaluates the expressions in turn, discarding all but the last's result. What I'm wondering though is why you insist on doing that before the opening curly braces. What exactly are you trying to achieve here that you can't achieve with a call to the function as first thing in the body?
Note that if you want to abort as early as possible, doing that in a separate baseclass (you can use private inheritance there) is probably the best solution. It's the only solution that allows you to prevent even the construction of other bases, which your solution doesn't.