Suppose I have a static method of my class that returns an object of the same type of my class. To create the object for example this method have to parse a string:
class C
{
public:
static C get_obj(const std::string& str)
{
C obj;
// Parse the string and set obj properties
return obj;
}
};
If, when I parse the string, I get an error and the object can't be constructed as a valid object, have I to throw an exception or what else?
Given that there is a possibility of failure in get_obj the failure must be reported back to the caller in some manner. This is typically either done by
Throwing an exception
Communicating the failure in the output of the method
In this particular case the only output of the method is a C instance. Given that throwing an exception is probably the best option for a method of this signature. The only other choice is to embed the success / failure inside the C object which you almost certainly don't want to do.
Another way to approach this problem is the try_parse pattern. Let a bool return indicate success / failure and return the constructed object on success through a reference parameter
bool try_parse(const std::string& str, C& obj) {
if (string is valid) {
obj = C(...);
return true;
}
return false;
}
I'd say you should throw an exception. This way you notify the client that the obj could not be obtained, and force him to deal with this.
If not important (not critical), you could return a special C that would act as a sentinel value indicating that something went wrong. The client will choose whether to do something about it or not.
I'd go with the exception. The second approach is not recommended.
Yes it is perfectly valid to throw an exception.
Its the same reason when constructing an object, if you cannot proceed with the construction of an object you have very little choice but to throw an exception.
Yes, you do need to throw an exception.
class C
{
public:
static C get_obj(const std::string& str)
{
try
{
C obj;
// Parse the string and set obj properties
return obj;
}
catch (int x)
{
cout "blahblah";
}
}
};
If the object cannot be constructed you risk a 0 variable, which can cause a lot of trouble further on
Related
I have a function that returns a 'vector'. However, sometimes during runtime the function can encounter an error in which it should not return the vector but instead return a value that can be checked by caller. Should I handle this by throwing an exception and catching it in the caller or should I change the return type of the function to 'std::pair' that stores a return value (0 or 1) and the vector. I don't want to exit the program with 'std::runtime 'error if the conditions occurs.
std::vector<int> function() {
std::vector ans;
//do stuff
if (something happens)
return -1;
return ans;
}
This sounds like a good time for an exception. Make a throwable type that can have a constructor argument, some sort of code that explains the problem. The catcher can check that code.
People will suggest std::variant and such instead, but that gets messy quite quickly and causes your function's signature to balloon. It also complicates the code at the callsite. There's no need for it here. Exceptions were literally designed for this use case.
My first choice would be a std::variant (it is better then std::optional since it can provide extra information in case of error and this is always beneficial in the future):
usign ErrorType = int;
using ReturnType = std::variant<std::vector<int>, ErrorType>
ReturnType function() {
std::vector ans;
//do stuff
if (something happens)
return -1;
return ans;
}
If your error is quite rare and exception could be cough in deeper caller level then exception is also a good/better way:
class MyException : public std::exception {
public:
MyException(int errorCode) : exception("MyException"), errorCode(errorCode)
{}
int code() const { return errorCode; }
private:
int errorCode;
};
std::vector<int> function() {
std::vector ans;
//do stuff
if (something happens)
throw MyException{ -1 };
return ans;
}
Please remember that in C++ exceptions are design in such way that they are zero cost when nothing is thrown. Trade of is that when something exception is thrown unwinding a stack is extremely slow (on some cpp-con someone said that it is x40 slower, I didn't measure it). This is the reason use of std::optional or std::variant instead of exception can be so beneficial.
AFAIK standard comity is working on new kind of exceptions mechanism which will behave like std::variant (similar how this is made in Swift).
You can use std::optional for it.
This question already has answers here:
How to handle failure in constructor in C++?
(8 answers)
Closed 7 years ago.
Is it possible to check the arguments of a constructor for certain constraints and if they're not met the object is not created and return a value to tell it failed to be created .
for instance .
Class Device
{
string id;
Device(string ID)
{
If (ID.Length != 7)
{
//Do not create Object
}
id == ID;
}
}
Here I only want 7 char long id String , not less not more ! if its not 7 char I don't want the Object created is it possible to do this ?
I couldn't think of any solution to this other than external function check which is something I want to stay away from !
The usual way would be to check the condition, and if it's not met, throw an exception.
Another possibility would be to accept an array of 7 characters, so the code won't compile if something else is passed. This tends to be trickier to get to work well in general though (e.g., it usually won't work if somebody passes an object of the wrong type, even something like a string that actually does contain 7 characters).
A sort of intermediate point would be to create a type specifically to hold your string of 7 characters, and throw an exception in its ctor if the length is wrong. This can give a little more granularity so it's easier to know what's wrong when the exception is thrown, as well as assuring that creating the Device object will succeed if you pass it a valid DeviceName (or whatever name you prefer) object.
You can throw an exception.
https://stackoverflow.com/a/7894215/2887128
Class Device
{
string id;
Device(string ID)
{
If (ID.Length != 7)
{
throw invalidObjectParametersException;
}
id == ID;
}
}
You could also adjust your design and wrap construction in some sort of factory.
One option I can think of is to throw an error if the condition is not met and catch that error in the function that creates the object.
Yes, you can implement a valid method, which will return if the created object is valid. In order to do that, without creating your real object, you would have to create an internal struct, which would become a private member of the owner class:
Class Device
{
struct DeviceImplementation {
string id;
Device owner;
DeviceImplementation (Device *owner, const string &id):
owner(owner),
id(id)
{
}
};
std::unique_ptr<DeviceImplementation> implementation;
public:
Device(const string &ID)
{
If (ID.Length != 7)
{
//Do not create Object
} else
implementation=std::unique_ptr<DeviceImplementation>(new DeviceImplementation(this, ID));
}
bool isValid() const {return implementation!=nullptr;}
}
No, a constructor can only return an object (or raise an exception).
If you want the chance to verify parameters or context, you should make:
a) the constructor private (so it cannot be called from outside the class anymore)
b) provide a static public method that returns an object (or, for example, NULL if it failed), and inside this method do your tests, and if they are successful call the private constructor and return the created object.
Of course, the outside code needs to able to handle a NULL return (or whatever you chose to do to signal that it failed).
This is a simple and common solution, but you can make up others with similar ideas.
Let us assume I always need the direkt return type of the function to be of a errorcode (success of calculation or failure) , then I will return some arguments as parameters. Is it better to define them as reference (and create them before empty) or better to return pointer?
Edit: I should be more precise: The errorcode is obligatory because I have to stick to the coding guidline given.
Possibility A:
ErrorCode func( some_parameters ... , ReturnType & result)
...
ReturnType result; // empty constructor, probably not good practice
func( some_parameters ..., result)
Possibility B:
ErrorCode func( some_parameters ... , ReturnType * result){
...
result = new ReturnType(...)
...
}
...
ReturnType * result; // void pointer
func( some_parameters ..., result)
...
delete result; // this is needed if I do not use a smart pointer
Even better: Maybe you have a more appropriate solution?
Edit: Please indicate which standard you are using, since unfortunatelly (guidelines) I have to stick to C++98.
I would do the following (and in general do)
1.) throw an exception instead of returning error codes
if this is not possible (for any reason)
2.) return the pointer directly (either raw or std::unique_ptr) and return nullptr for failure
if return type has to be bool or not all objects returned are (pointers / heap allocated)
3.) return your error code (bool or enum class) and accept a reference parameter for all objects that are to be initialized (must have objects so to speak) and pointers to objects that may be optionally created / initialized
if the object cannot be created in advance to the call (e.g. because it is not default constructible)
4.) pass a reference to a pointer (raw or std::unique_ptr) or a pointer to a pointer, which will then be filled by the function
std::optional (or similar) may be an option if you only have a true/false return code.
I don't like returning std::pair or std::tuple because it can make your code look quite annoying if you have to start using .first/.second or std::get<>() to access your different return types. Using std::tie() can reduce this a little bit, but it is not (yet) very comfortable to use and prevents the use of const.
Examples:
std::unique_ptr<MyClass> func1() { /* ... */ throw MyException("..."); }
std::unique_ptr<MyClass> func2() { /* ... */ }
ErrorCode func3(MyClass& obj, std::string* info = nullptr) { /* ... */ }
ErrorCode func4(std::unique_ptr<MyClass>& obj) { /* ... */ }
int main()
{
try
{
auto myObj1 = func1();
// use ...
}
catch(const MyException& e)
{
// handle error ...
}
if(auto myObj2 = func2())
{
// use ...
}
MyClass myObj3;
std::string info;
ErrorCode error = func3(myObj3, &info);
if(error == ErrorCode::NoError)
{
// use ...
}
std::unique_ptr<MyClass> myObj4;
ErrorCode error = func4(myObj4);
if(error == ErrorCode::NoError)
{
// use ...
}
}
Edit: And in general it is advisable to keep your API consistent, so if you already have a medium or large codebase, which makes use of one or the other strategy you should stick to that (if you do not have good reasons not to).
This is a typical example for std::optional. Sadly it isn't available yet, so you want to use boost::optional.
This is assuming that the result is always either "success with result" or "fail without result". If your result code is more complicated you can return
std::pair<ResultCode, std::optional<ReturnType>>.
It would be good style to to use the return value for all return information. For example:
std::tuple<bool, ReturnType> func(input_args....)
Alternatively, the return type could be std::optional (or its precursor) if the status code is boolean, with an empty optional indicating that the function failed.
However, if the calculation is supposed to normally succeed, and only fail in rare circumstances, it would be better style to just return ReturnType, and throw an exception to indicate failure.
Code is much easier to read when it doesn't have error-checking on every single return value; but to be robust code those errors do need to be checked somewhere or other. Exceptions let you handle a range of exceptional conditions in a single place.
Don't know if it's applicable in your situation but if you have only two state return type then maybe just return pointer from your function and then test if it is nullptr?
I want to parse a simple text file and create an object from the data it contains. I'm using C++11 for this (and I'm not fluent).
In case of any kind of error (e.g. missing file or invalid text) I wish to tell the caller of my parsing function what went wrong, providing information like what kind of error occurred and where in the file.
I don't consider exceptional that errors occur while parsing, so it seems exceptions are not the way to go.
I thought of returning a struct with all the info, including the resulting parsed object in case of success:
struct ParsingResult
{
bool success;
int errorCode;
int errorLine;
ParsedObject object;
}
However I'm not convinced by this solution because, in case of errors, I must still provide a ParsedObject. I can define a default constructor for that, of course, but by it's nature a ParsedObject makes sense only when the parsing is successful.
I could change ParsedObject to ParsedObject*, but I'm reluctant to use pointers when not necessary, and I wonder if this can be avoided.
My question: can you suggest a better solution to this problem? What is it?
struct Obj
{
// your object from the data...
}
struct ParseError
{
int errorCode;
int errorLine;
}
class Parser
{
ParseError m_error;
// other things
public:
bool parse(const std::string& filename, Obj& parsedObject)
{
// Open file, etc...
//parsedObject.property1 = some_value;
// if something is wrong, set m_error and return false;
// return true if ok
}
ParseError getLastError() { return m_error; }
}
// in your code
Parser p;
Obj o;
if(!p.parse("filename", o))
{
// ParseError = p.getLastError();
}
You can use a
unique_ptr<ParsedObject>
or
shared_ptr<ParsedObject>
whose default constructor can be compared to null in case of unsuccessful parsing.
Avoiding raw pointers will free you from having to free memory :)
I have read answers to following questions ->
c++ exception : throwing std::string
c++ Exception Class Design
My requirement is to catch exceptions and allow a mechanism to reformat the error messages and then re-throw the exceptions.
So I thought of writing my exception class which will provide a method to reformat the error message at various catch points.To make reformatting easy, I'm embedding a string object in myexception_base class.
I have also referred to this article -> http://www.boost.org/community/error_handling.html which clearly says not to embed string objects in exception classes.
The article also has a quote "Peter Dimov makes an excellent argument that the proper use of a what() string is to serve as a key into a table of error message formatters." but it does not elaborate on it any further.
I have written the code as given below and my questions are -
1) If I don't embed a string object in my exception class, it will make it difficult to reformat the what messages. Please tell me How shall I approach to my requirement without embedding a string object in my exception class?
2) If I carry on with my current approach of embedding a string object and providing a method to format error message. Is my way of handling some scenarios correct ? (Issue 1 and Issue 2 in which error msg doesn't get formatted)
Issue 1 - wrong exception getting propagated to catch points ?
Issue 2 - Error Message not getting formatted in some scenarios ?
Issue 1 and Issue 2 are mentioned in comments in code below.
Kindly have a look at the code. I have given lot of comments in code so lines of code has increased but if I remove the comments it has very less lines of code.
#include <string>
#include <exception>
#include <iostream>
using namespace std;
class myexception_base : public exception {
private:
string error_msg;
public:
myexception_base(const char* str) : error_msg(str) {
// std::string here here can throw an exception while error_msg
//initialisation through MIL.
// myexception_base object will not be constructed
// and wrong exception will be propagated to catch point(Issue 1)
}
const char* what() const throw() {
try {
return error_msg.c_str();
} catch (...) {}
// c_str can throw.
// I can't remove throw specification from what()
// because what() in base std::exception has throw() specification
// In case c_str() throws an exception program will terminate
// So to stop abnormal termination of program c_str
// is wrapped in a try catch block to ignore std::string exception
// program will not terminate but what message is not reformatted
// in such scenario (Issue 2)
}
void append_error_msg(const char* str) {
error_msg.append(str);
// append can throw
// Again error_msg will not be formatted (Issue 2)
}
~myexception_base() throw() {
}
};
void f();
void f2();
void f() {
throw myexception_base("Error Msg1");
}
void f2() {
//Some intermediate Catch point will reformat e.what() msg
//by appending an error msg2
try {
f();
}
catch (myexception_base& e) {
e.append_error_msg(": Error Msg2");
throw;
}
}
int main () {
try {
f2();
}
catch(const exception& e) {
// Finally the exception is caught in the upper most layer
// and proper error_msg is given to user
cout<<e.what()<<"\n";
}
}
According to the boost documentation embedding classes which might throw during their lifetime are not an excellent candidate to be used in the exception handler mechanism, so I would like to suggest that you will simply use the good old C way of handling strings. It will require some extra effort to bring it up and running but with them you have eliminated one source of error.
So, basically there are two approaches:
In the myexception_base you declare the error_msg as being an array of N chars. In the append_error_msg you carefully check that the length of the NEW string (after the append) is not greater than N and if it is not, then you use strcat or one of the other C string handling methods. This approach might be good, since it does not allow memory leaks through the exception handling mechanism, however you can have only a limited length of error message.
In the myexception_base you declare the error_msg as being a char* (a char pointer). In the constructor you callocmemory for it (do not use new since new might throw) and in the append_error_message you realloc the pointer to be the new size (ie. old size + string to be appended.size + 1 for the 0) and then memcpy to the requested position (ie. at the position of the end of the old string in the newly allocated string). Of course, do not forget to check all the allocations/re-allocations that they have returned a valid value otherwise you might get funny behavior. And last, but not least, to avoid the classical memory leaks, free the memory of the char* in the destructor.
Good luck!