I'm really struggling with throwing an error message that includes an argument from the function. I know I can do:
throw std::out_of_range("Empty tree");
What I am struggling with is another error I am supposed to throw, which is:
"Cannot find ceil for key <key>"
As you can see, I am supposed to include the key for which I cannot find the ceil for. I have the key as a variable in the function from which I am throwing the exception, but I have no idea how to include it in what will eventually be printed by e.what().
EDIT: This is a template function as a member of a class, so key is just type T right now. Hence why I think formatting it as a c string wasn't working.
The standard exceptions only take a string as an argument:
e.g. out_of_range, see apache.org docs
namespace std {
class out_of_range : public logic_error {
public:
explicit out_of_range(const string& what_arg);
};
}
You could use any method to build the string beforehand, and then pass that as the parameter to the exception.
Example:
#include <string>
#include <sstream>
#include <stdexcept>
std::ostringstream oss;
oss << "Cannot find ceil for key " << key;
std::string errorString = oss.str();
throw std::out_of_range(errorString);
For other ways to create the string, see C++ create string of text and variables
Related
I'm sure this is something simple, but wasn't able to find any other posts clearly specifying this, though I'm sure there must be one buried somewhere.
In C++, when using a try catch block in the below manner, how can I append a string variable to the error message?
I get an unhandled exception when trying to do this. Is it something to do with what type is passed back? Appears to be returning a string versus a char*. if that is correct, would that cause the issue? How would I adjust for this? I tried adding an additional catch (const string my_msg), but that did not work, either.
string msg = "message";
try{
if (...)
throw "My error " + msg;
}
catch (const char* my_msg){
cerr << my_msg << endl;
}
"My error " + msg is an operation that concatenates a const char* string and an std::string. This operation results in a temporary variable of type std::string. Therefore, the thrown variable must be caught with a catch clause of type std::string.
catch (const std::string& my_msg){
cerr << my_msg << endl;
}
Still, it is better practice to have your exceptions derive from std::exception. You don't need to create your own exception class though, as there is std::runtime_error and its derivations, which provides useful classifications of common runtime exceptions.
There are many cases where you need to have a distinct type for your exceptions, often of which may be project or domain specific. In C++11, making your own exception type is as easy as this
struct my_exception : std::runtime_error {
using std::runtime_error::runtime_error; // Inherit runtime_error's constructors
};
This uses C++11's inheriting constructors.
Our professor gave us a shell to make a program in. In it he gave us a class called "Maker", and it is capable of throwing exceptions. I'm confused about how to throw and catch the error, given the format of the constructor that he has provided.
He gave us his own special exception header file called CycleFoundException.h, which looks like this:
#include <iostream>
#include <exception>
using namespace std;
class CycleFoundException: public exception {
// Don't add code
};
Here is the Maker.h header file:
#include "CycleFoundException.h"
class Maker
{
private:
// insert instance variables
public:
Maker(int x) throw (CycleFoundException);
};
And finally the cpp shell, Maker.cpp:
#include Maker.h
Maker::Maker(int x) throw (CycleFoundException){
//add code here
}
int main()
{
return 0;
}
I've never seen a constructor declaration like this. Why is the "throw (CycleFoundException)" be tagged onto the declaration of the constructor? Is that necessary?
And how would I throw an exception given this format? Would I still do it the same way I would otherwise, aka if a certain condition is not met then throw the exception (from within the body of the constructor)? Thanks.
This is simply a way to say what kinds of exceptions a function is allowed to throw:
Maker::Maker(int x) throw (CycleFoundException)
means that Maker::Maker(int) is only allowed to throw CycleFoundException exceptions, nothing else. This is called an "exception specification."
Note that the C++ standard has deprecated this mechanism. It should not be used anymore. You should probably inform your professor about it ;-) They were always problematic: http://mu2e.fnal.gov/public/hep/computing/standards/C++FAQ.shtml#exceptionspec
The exercise says:
Create a Text class that contains a string object to hold the text of
a file. Give it two constructors: a default constructor and a
constructor that takes a string argument that is the name of the file
to open. When the second constructor is used, open the file and read
the contents into the string member object. Add a member function
contents() to return the string so (for example) it can be printed. In
main( ), open a file using Text and print the contents.
This is the class that I wrote:
class Text {
string fcontent;
public:
Text();
Text(string fname);
~Text();
string contents();
};
I haven't understood everything of this exercise. It asks to create a function contents(), that returns a string, but it doesn't says what the function has to do...
Neither what the default constructor has to do.
Could someone help me?
The function has to return the contents of the file, which is stored (in your case) in fcontents.
string Text::contents()
{
return fcontent;
}
The default constructor doesn't have to do anything in this case.
Text::Text(){}
EDIT:
Seeing how many comments there are below with new problems, I'm going to recap and answer the rest of the questions here.
in Text.h you have:
#ifndef TEXT_HH
#define TEXT_HH
#include <string> //[1]
class Text {
std::string fcontent;//[2]
public:
Text();
Text(std::string fname);
~Text();
std::string contents();
};
#endif
and Text.cpp has
// Text.cpp
#include "Text.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
Text::Text() {}
Text::Text(string fname) {
fstream f;
f.open(fname.c_str(), ios::in);//[3]
//[4]
std::stringstream stream;
while(true)
{
char buffer[1000];
f.getline(buffer, 1000);
if(f.good())
{
//This actually adds an extra newline at the end
stream << buffer << '\n';
}
else
{
break;
}
}
fcontent = stream.str();
//remove extra newline
fcontent.erase(fcontent.begin() + fcontent.size() - 1);
f.close();//This is technically unnecessary, but not bad either
}
string Text::contents() {
return fcontent;
}
Text::~Text() {}//[5]
Point 1: The header file <string> contains the class definition for std::string, the C++ string. This should not be confused with <cstring> which contains functions for manipulating C strings (const char *, const char[], etc).
Point 2: The string class exists in the ::std namespace, which means we have to either use std::string every time we want that class or use using namespace std; to pull this class into the global scope. In the header file we prefer the former method because the using declaration doesn't go away, which means that the namespace will be changed for every header and source file that includes this one, which we want to avoid in general (ie. always). In the cpp file however, there is no problem using the using declaration and we do so.
Point 3: fstreams take a C string as the filename parameter, we can get the corresponding C string from a C++ string with the call c_str(). This returns a const char *.
Point 4: To read the whole text file into a string is less obvious than it seems because the way streams deal with eof (end-of-file) and state-checking stuff. In short it will read one more time than you want it to (I know, wanting is subjective, but is close enough I think) before setting the eof flag. That's why the state is checked after calling get and before adding what's been read to our stringstream. Streams are a fairly elaborate topic so I won't go into it in more detail here.
Point 5: Destructors on objects (non-pointers, like our fcontents is) are called automatically, so we don't need to do anything to make sure that our fcontents string is destroyed when our Text object is destroyed. When we allocate something dynamically with new that's when we have to worry about calling delete on it when we want to destroy it.
I'm convinced at this point that I should be creating subclasses of std::exception for all my exception throwing needs. Now I'm looking at how to override the what method.
The situation that I'm facing, it would be really handy if the string what returns be dynamic. Some pieces of code parse an XML file for example, and adding a position or line number to the error message is useful to me.
I am trying to follow the Boost Exception handling guidelines.
What I'd like to know:
what returns a const char *, which implies any catcher is likely not going to free the string. So I need some other place to store the result, but where would that be? (I need thread-safety.)
what also includes throw() in its signature. While I can prevent my what from throwing anything, it seems to me that this method really isn't intended for anything too dynamic. If what is not the right place, then where should I be doing this instead?
From the answers I've gotten so far, it looks like the only way to accomplish this is by storing the string in the exception. The Boost guidelines recommend against this, which is confusing to me, because std::runtime_error does just that.
Even if I were to use a C-string, I'd have to use a statically sized buffer, or do memory management which can fail too. (I'm wondering if this is actually the only thing that can go wrong in std::string's copy-constructor. That would mean I won't gain anything using dynamically allocated C-strings.)
Is there any other option left?
My exception classes generally don't have anything but the constructor and look along these lines:
class MyEx: public std::runtime_error
{
public:
MyEx(const std::string& msg, int line):
std::runtime_error(msg + " on line " + boost::lexical_cast<string>(line))
{}
};
An arbitrary example, but it is the base class that handles managing the what() message.
But if you want to, you can also only assign the base part of the exception object, after you've put together the message in the constructor body.
#include <stdexcept>
#include <string>
#include <sstream>
class MyEx: public std::runtime_error
{
public:
MyEx(const std::string& msg, int line):
std::runtime_error("")
{
std::stringstream ss;
ss << msg << " on line " << line;
static_cast<std::runtime_error&>(*this) = std::runtime_error(ss.str());
}
};
#include <iostream>
int main()
{
try {
throw MyEx("Evil code", __LINE__);
}
catch (const std::exception& e) {
std::cout << e.what() << '\n';
}
}
However, regarding the boost's guidelines, perhaps you should pay attention to the point that numeric data (positions and lines) might best be made available as numbers through other methods. The guidelines say to worry less about the what() message.
Boost's guidelines appear to be based on two assumptions: copying the exception object might throw another exception, and the what() string isn't a robust or reliable tool. These are valid concerns if you're writing a library that will see wide use in a variety of environments. If you have better knowledge of how the exception will be used, you can judge if these concerns are justified or much ado about nothing. Programming is all about a series of tradeoffs, and the tradeoffs that make sense for the Boost developers might not apply to you.
Well, no problem, you can simply implement the constructor of your derived exception class to format the string you'll return from what(). Free the buffer you use for that in the destructor.
I'm accepting UncleBens' answer, because I consider it technically the most correct and complete answer to my original question.
For reference, I actually picked a different solution, and stopped using what altogether. I've refactored the code I have now to use something like this as the base exception class:
struct Exception : public virtual std::exception
{
virtual const char* what() const throw()
{
try {
return typeid(this).name();
}
catch (const std::exception& e) {
return "<unknown exception>";
}
}
// Extended description; may throw.
virtual void describe(std::ostream& out) const = 0;
};
Basically just filling what with the most meaningful thing I could find without bothering with it anywhere else. I'm going to see how this fares, I guess.
I have a C++ class and I am trying to run it in Ubuntu:
#ifndef WRONGPARAMETEREXCEPTION_H_
#define WRONGPARAMETEREXCEPTION_H_
#include <iostream>
#include <exception>
#include <string>
using namespace std;
#pragma once
class WrongParameterException: public exception
{
public:
WrongParameterException(char* message): exception(message) {};
virtual ~WrongParameterException() throw() {};
};
#endif
when I try to compile it, the compiler gives me this error:
WrongParameterException.h: In constructor ‘WrongParameterException::WrongParameterException(char*)’:
WrongParameterException.h:14: error: no matching function for call to ‘std::exception::exception(char*&)’
/usr/include/c++/4.3/exception:59: note: candidates are: std::exception::exception()
/usr/include/c++/4.3/exception:57: note: std::exception::exception(const std::exception&)
Can anyone tell me what am I doing wrong? I tried changing the message variable to string or const string or const string& but it didn't help.
Here is how I use the new exception that I created from main:
try
{
if ((strToInt1 == -1) || (parameters[1] == NULL) || (strToInt3 == -1) || (parameters[3] != NULL))
{
throw WrongParameterException("Error in the config or commands file");
}
}
catch(WrongParameterException e)
{
log.addMsg(e.what());
}
First, #pragma once is the wrong way to go about it, learn about header include guards. Related question on SO explains why using #pragma once is the wrong way to go about it. Wikipedia explains how to use include guards which serve the same purpose without any of the downsides.
Second, you are calling the constructor of std::exception with a parameter it does not know, in this case a pointer to a character array.
#include <stdexcept>
#include <string>
class WrongParameterException : public std::runtime_error {
public:
WrongParameterException(const std::string& message)
: std::runtime_error(message) { };
};
Would probably be what you want. For more information on exceptions, check out C++ FAQ Lite article on Exceptions and the exceptions article at cplusplus.com.
Good luck!
std::exception does not have a constructor that takes any kind of string, only a virtual what() method that returns the exception description.
You will have to store the string yourself and return it from there.
My advice would be:
Inherit from std::runtime_error. As advised by X-Istence above. It is conceptually a runtime error, and also the std::runtime_error constructor accepts a std::string as argument describing what happened.
About your catching the exception. I'd use catch(WrongParameterException const& e)
(note the const reference) instead of catch(WrongParameterException e), because first, the exception is normally constant in your case, and, also, using the reference, you catch any subclass of WrongParameterException in case your code evolves with some more refined exception handling.
std::exception's constructor doesn't take a string argument. You're trying to give it one, which is what causes the compile error.
You need to store your string, which would be better to handle as a std::string rather than a raw pointer, and return it from the what() method.
Looking at the declaration of the exception class in MS VS2K5, the constructor you want is:
exception (const char *const&);
so try changing your constructor to:
WrongParameterException (const char *const message)
and see if that helps. Otherwise, store the pointer in your own class and implement all the relevant methods.
A simple solution is to design your exception diferently. Here is a simple example:
class MyException : public Exception
{
public:
MyException(CString strError) { m_strError = strError; }
CString m_strError;
};
Then you can simply use your exception message as you please. This is because Exception does not have a contructor that excepts a String, so you have to stlre it on your own.