Preventing construction by throwing exception before constructor body - c++

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.

Related

Unable to call member function pointer that is inside a struct

I've been racking my brain over getting the syntax right on declaring, defining and finally calling a member function pointer inside my program.
I'm writing a window manager with Xlib, and am trying to enable the user to define all key bindings in a vector of Keybinds. The Keybind struct contains more member variables, which I have left out here for the sake of brevity.
Here's what I've got so far.
Keybind, a struct containing a member variable, func, that points to a MyClass member function.
struct MyBind {
MyBind(void (MyClass::*_func)(const XKeyEvent&))
: func(_func) {}
void (MyClass::*func)(const XKeyEvent&);
}
Declaration and populating of a vector that holds user-defined Keybinds.
// in my_class.hh
std::vector<MyBind*> my_binds_;
// in my_class.cc, constructor
my_binds_.push_back(new MyBind( &MyClass::do_this ));
my_binds_.push_back(new MyBind( &MyClass::do_that ));
At this point, everything compiles and runs.
Now, when I try to delegate work by iterating over the my_binds_ vector, things go wrong. It is worth noting that I've left out error handling and other member variable accesses for clarity.
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(my_bind->*func)(e); // erroneous line
}
}
This should be the correct syntax, but it fails to compile, stating error: ‘func’ was not declared in this scope (g++, similar error from clang++).
This is weird to me, as replacing the erroneous line of code with auto test = keybind->func; does compile.
What am I doing wrong? Is there a better way to handle user key bind definitions? Thanks!
It would be best to use std::function and forget about raw member-function pointers altogether. They will only bring you pain :)
The problem with you code is that you only have a pointer to a method but no object. Your bind struct should also store an object pointer to call the method on:
struct MyBind {
MyBind(MyClass *obj, void (MyClass::*_func)(const XKeyEvent&))
: obj(obj), func(_func) {}
MyClass *obj;
void (MyClass::*func)(const XKeyEvent&);
void operator()(const XKeyEvent& event) const
{
(obj->*func)(event);
}
}
And then use it like this:
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(*my_bind)();
}
}
I've added a call operator to the bind struct for convenience. Note that the ->* operator is applied to the object the method belongs to.
This is not an answer, rather a pointer to your answer or my so-question :)
You had to use
(this->*(my_bind->func))(e);
instead of:
(my_bind->*func)(e);
I have re-created your error msg and asked a question after many different attempts.
See this( pointer to your answer ;) ): How to call pointer to member function, which has been saved in a vector of custom struct?
MyBind holds the pointer to member function of some instance of MyClass. Therefore in order to call these function pointers, you need to explicitly tell using this keyword, for which instance of MyClass you want the func to be called.

Reference qualifiers and deleted member methods

Consider the following code:
#include<utility>
struct S {
void f(int) = delete;
void f(int) && { }
};
int main() { }
It doesn't compile saying that the member method cannot be overloaded and it makes sense, of course.
On the other side, the following code compiles:
#include<utility>
struct S {
void f(int) & = delete;
void f(int) && { }
};
int main() {
S s;
// s.f(42); <-- error, deleted member method
std::move(s).f(42);
}
Is that legal code?
Wouldn't it be possible to define two completely different interfaces within the same class, the former to be used with lvalues, the latter with rvalues?
Apart from the fact that it doesn't make much sense, but it really hurts me.
Shouldn't a deleted function be deleted as a whole, instead of deleted only if you are a lvalue?
Which is the purpose of this feature? Is it the classic obscure corner case or is there something more I can't see?
Sometimes it makes sense to prohibit certain operations if object is l- or r-value.
Imagine RAII wrapper for FILE*. It opens file in constructor, closes it in destructor, turning C feature requiring manual control to C++ exception-safe class. To interact with C interface, there is a .get() member which returns raw pointer. Someone might write:
FILE* file = CFile("file.txt").get();
It would compile, but it is wrong: file would be closed as soon, as file variable would be initialized. If you delete an r-value overload (on never provide it in the first place), then it would lead to compile-time error and save us from bug-hunting.

Code simpler than lambda for a call in constructor that uses an output parameter function for initializing a const member

In the header, I have
class CSomeClass
{
const GUID m_guid;
public:
CSomeClass();
///...
}
And in the source file
CSomeClass::CSomeClass()
, m_guid(
[]() {
GUID g;
::CoCreateGuid(&g);
return g;
}()
)
{
}
As you know Guids can be used as identifications not meant to be changed. Given the ::CocreateGuid() function provides what I want as an output parameter, instead of returning it, I cannot use directly a simple call to the function for initializing the m_guid member field, that is constant.
So, a consequence of its constness, is that it must be initialized before the opening bracket in initializer list, and therefore not be simply assigned with a call to ::CocreateGuid() in the constructor body.
Is there a simpler way to initialize it than this lambda expression?
When the lambda expression is correct, I would use a helper function for that:
GUID create_guid()
{
GUID g;
::CoCreateGuid(&g);
return g;
}
CSomeClass::CSomeClass() : m_guid(create_guid()) {}
In addition, create_guid() has a meaning by itself and could be reused (even if making it a implementation detail is possible/correct).
You should consider wrapping the GUID in its own class:
class CGUID
{
public:
CGUID()
{
CoCreateGuid(m_guid);
}
const GUID& guid() const { return m_guid; }
// Maybe some useful functions:
bool operator==(const CGUID&) const;
private:
GUID m_guid;
};
Now you can use the above as a member:
class CSomeClass
{
const CGUID m_guid;
...
Here we abstract your pattern:
template<class A>
A co_make( HRESULT(*f)(A*) {
A a;
HRESULT hr = f(&a);
Assert(SUCCEEDED(hr));
if (!SUCCEEDED(hr))
throw hr;
return a;
}
CSomeClass::CSomeClass()
m_guid(
co_make(&::CoCreateGuid)
)
{}
where we detect failure and assert then throw if that is the case.
I'm not sure this is simpler.
Really, write a GUID make_guid() function, stick it in some header, and call it.
Your proposal is the simplest way to initialize the constant instance member.
Don't get scared of lambdas, as a matter of fact, in general it is a new style recommendation to use lambdas for complex initializations of constants and references because they share the property of only being initialized at the point of declaration (or instance member initialization in the initializer list).
Furthermore, your code triggers the "named return value optimization" and there is no copy construction at the return from the lambda.
The interface to CoCreateGuid is deficient because it requires an output argument.
If you insist on not using the lambda, I think the next most practical alternative is to, in the constructor body, de-constify using const_cast to pass it to CoCreateGuid.
Mind you that one you enter the body of a constructor the language considers all individual members to have been properly initialized, and will invoke destructors for them should an exception happens, this makes a very big difference whether something is initialized in the initializer list or left with a binary pattern of garbage.
Finally, unfortunately you can't just call CoCreateGuid with a de-constified reference to m_guid in the lambda, because the lambda will still return a value and that will overwrite the member. It is essentially the same as what you already wrote (with the exception of the default constructor of g)
It would be simpler if you declare m_guid as a mutable instance member as opposed to const. The difference is that mutable are like a const for users of a class but a perfectly fine lvalue within the class

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

Object construction/Forward function declaration ambiguity

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.
Hello,
It wasn't for just a few times that I stumbled into an object construction statement that I didn't understand, and it was only today that I noticed what ambiguity was being introduced by it. I'll explain how to reproduce it and would like to know if there's a way to fix it (C++0x allowed). Here it goes.
Suppose there is a class whose constructor takes only one argument, and this one argument's type is another class with a default constructor. E.g.:
struct ArgType {};
class Class
{
public:
Class(ArgType arg);
};
If I try to construct an object of type Class on the stack, I get an ambiguity:
Class c(ArgType()); // is this an object construction or a forward declaration
// of a function "c" returning `Class` and taking a pointer
// to a function returning `ArgType` and taking no arguments
// as argument? (oh yeh, loli haets awkward syntax in teh
// saucecode)
I say it's an object construction, but the compiler insists it's a forward declaration inside the function body. For you who still doesn't get it, here is a fully working example:
#include <iostream>
struct ArgType {};
struct Class {};
ArgType func()
{
std::cout << "func()\n";
return ArgType();
}
int main()
{
Class c(ArgType());
c(func); // prints "func()\n"
}
Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works
{
funcPtr();
return Class();
}
So well, enough examples. Anyone can help me get around this without making anything too anti-idiomatic (I'm a library developer, and people like idiomatic libraries)?
-- edit
Never mind. This is a dupe of Most vexing parse: why doesn't A a(()); work?.
Thanks, sbi.
This is known as "C++'s most vexing parse". See here and here.
Let's simplify a little.
int f1();
What's that? The compiler (and I) say it's a forward declaration for a function returning an integer.
How about this?
int f2(double );
The compiler (and I) say it's a forward declaration for a function taking a double argument and returning an int.
So have you tried this:
ClassType c = ClassType(ArgType());
Check out the c++ faq lite on constructors for explanations and examples
Based on the "C++0x allowed", the right answer is (probably) to change the definition to:
Class c(ArgType {});
Simple, straightforward and puts the burden entirely on the user of the library, not the author!
Edit: Yes, the ctor is invoked -- C++ 0x adds List-Initialization as an unambiguous way to delimit initializer lists. It can't be mis-parsed like in your sample, but otherwise the meaning is roughly the same as if you used parentheses. See N3000, the third bullet point under §8.5.4/3. You can write a ctor to receive an initializer list as a single argument, or the items in the initializer list can be matched up with the ctor arguments individually.