is it possible to recover from vector "out of reach" error in C++?
Like this function:
vector<int> numbers;
bool isAccessable(int i)
{
try
{
numbers[i];
catch (...)
{
return false;
}
return true;
}
it's possible in C#, but c++?
If you just want to check whether the index is in range, then simply:
return i < numbers.size();
(You should also either compare with zero, or change the index to an unsigned type; size_t is the type usually used for array indexes.)
If you want to try to access the value, and throw an exception if the index is out of range, then use at rather than []:
try {
do_something_with(numbers.at(i));
return true;
} catch (std::out_of_range const &) {
return false;
}
In C++ there is no range check for operator[], but there is for vector::at().
Try
numbers.at(i);
instead.
Use std::vector::at() member function. It throws an out_of_range exception.
Related
What I'm trying to do is write code that breaks out of a for loop if an exception is thrown. Can this be achieved by simply using return in the catch block? or do I have to use break somehow?
for example, 1. will this function return 0 or 1?
2. will the first return statement break the for loop or
3. will it keep on looping?
Thank you in advance!!
int main() {
for (int i = 0; i < 2; i++) {
try {
if (i = 0) {
throw fake_error;
}
}
catch(fake_error) {
return i;
}
}
return i;
}
Any block can try catch, though while allowed I recommend to use a bigger scope. (exceptions are the biggest exception to the "don't pay for what you don't use" rule in c++).
To avoid having to put your exception into the inner loop you can create your own exception and put the information you want to have available in the catch block inside the exception. So this example shows you how to do that, also catch exceptions by const& this will avoid unecessary copying and/or modification of the exception content.
#include <stdexcept>
//-------------------------------------------------------------------------
// declare/define an exception that can hold an int.
class my_exception :
std::exception
{
public:
// always declare constructors with one parameter explicit
// or they can be used in implicit type-conversions
explicit my_exception(const int value) :
m_value{ value }
{
}
// accessor to data
const int& value() const noexcept
{
return m_value;
}
private:
int m_value;
};
//-------------------------------------------------------------------------
int main()
{
int retval{ 0 };
// with our own exception we can
// move the try-catch block out of the loop.
try
{
for (int i = 0; i < 2; ++i)
{
if (i == 1) throw my_exception(i);
}
}
catch(const my_exception& e)
{
retval = e.value();
}
return retval;
}
Yes.
C++ allows try/catch inside any block of statements, including a for() loop block.
However, you may want to consider doing it otherwise if possible just because it is slow (if the for() is only expected to go over a small number of iterations, then not big deal).
Please consider this scenario.
I'm creating a function for [] operator as in the std::vector whose inner body is like this:
int temp;
if(argument >= 0 && argument < size) {
return &my_vector[i];
} else {
cout << "out of bounds" << endl;
//i need to return here something but this gives me an error: local variable cannot be returned by reference.
return &temp;
}
where argument is the argument passed to the function. The return type for this function is 'T*'.
I'm looking for both the read and write cases:
vector[100] = 1;
and int answer = vector[100];
That's why they are returned by reference.
What should be returned in the else part?
First of all, you are not returning a reference, but a pointer, which makes the method not very useful. Instead of
vector[100] = 1;
int answer = vector[100];
You would have to write
*vector[100] = 1;
int answer = *vector[100];
To get what you want you should return a reference not a pointer. Ie return type should be T& not T*.
Then you have basically two options. Either you mimic vectors operator[]. It does not do any bounds checking. It is up to the caller to make sure to pass valid indices:
return my_vector[i]; // thats all (assuming my_vector[i] returns a reference)
The other option is to throw an exception as std::vector::at does:
if(i >= 0 && i< size) {
return my_vector[i];
} else {
throw std::out_of_range("invalid index");
}
You cannot return a reference to a local variable, because that reference is dangling as soon as the method returns and the local variables lifetime ended.
You have to choose which approach fits better. std::vector offers both. Typically when the method is called in a loop:
for (size_t i=0; i<size;++i) {
foo[i] = i;
}
You do not want to incur the overhead of checking the index on each access. On the other hand sometimes indices are computed and the caller wants to have the bounds check encapsulated rather than doing it manually:
try {
size_t index = some_function(); // is this a valid index?!?
foo.at(i) = 42; // let at check it
} catch(...) {
//...
}
PS: You typically need two overloads for those accessors, one const and one non-const, returning const T& and T&, respectively.
I have a function that search a vector and returns the item if it is found. But I want to know that best software appraoch to handle if it is not found.
I have created a function and could return -1 or something but that wouldn't match the return type.
koalaGraph::PVertex Koala::lookUpVertexbyName(const std::string&vertexName, const std::vector<koalaGraph::PVertex>& koalaVertices) {
for (size_t i = 0; i < koalaVertices.size(); i++) {
if(koalaVertices[i]->info.name == vertexName)
return koalaVertices[i];
}
}
If a situation is encountered where the item being searched for is not in the vector then program will exit.
You can use std::optional
#include <optional>
std::optional<koalaGraph::PVertex>
Koala::lookUpVertexbyName(const std::string&vertexName,
const std::vector<koalaGraph::PVertex>& koalaVertices) {
for (size_t i = 0; i < koalaVertices.size(); i++) {
if(koalaVertices[i]->info.name == vertexName)
return koalaVertices[i];
}
return {};
}
int main()
{
Koala k;
//...
auto maybeVertex = k.lookUpVertexByName("foo",vertices);
if(maybeVertex)
koalaGraph::PVertex&& vertex = *maybeVertex;
//alternatively
if(maybeVertex.has_value())
//found
}
You could use a for-loop and return a iterator.
std::vector<koalaGraph::PVertex>::const_iterator
Koala::lookUpVertexbyName(
const std::string&vertexName,
const std::vector<koalaGraph::PVertex>& koalaVertices)
{
for(auto iter = koalaVertices.begin(); iter != koalaVertices.end(); ++iter) {
if(koalaVertices[i]->info.name == vertexName) {
return iter;
}
}
return koalaVertices.end();
}
Further you check if you got end back. end indicates if the value was found or not.
auto iter = <fucntioncall> // lookUpVertexbyName
if (iter == <vector>.end() {
// abort or do what ever you want
}
To use the value you have to dereference the iterator. DON'T derefence the end-iterator, it will lead you to neverland -> undefined behavior.
std::string test = *iter;
Why not use std::find_if instead of reinventing the wheel. See this link.
struct equal
{
equal(const std::string& vertexName) : vertexName_(vertexName) { }
bool operator()(const koalaGraph::PVertex& pVertex) const
{
return pVertex->info.name == vertexName_;
}
private:
std::string vertexName_;
};
And then:
std::find_if(koalaVertices.begin(), koalaVertices.end(), eq(vertexName));
Regarding handling the errors in function as it has already been stated there are multiple approaches that one can take. Returning an iterator instead of object(you will avoid copying this way too) is one of them. end() iterator would then indicate that the name was not found.
There are three ways to exit a function:
Return a value
Throw a value
Call std::abort or std::exit (possibly indirectly)
(std::longjmp which you shouldn't use)
If you don't do any of the above, then behaviour will be undefined. If you don't want to do 1., then your options are 2. or 3. Abort and exit will terminate the process. A throw can be caught, but an uncaught throw will cause std::abort.
Note that just because you don't find a value, it's not necessarily impossible to return some value. What you can do is return a "sentinel" value that represents "not found". For example, std::string functions that return an index will return std::string::npos when there is no result. Functions returning a pointer might return null, and functions returning an iterator would return an iterator the the end of the range.
If there is no representation of your return type that could be reserved for a sentinel, there is a way to add such representation by wrapping the return type with additional state. The standard library has a generic wrapper for this: std::optional.
Another wrapper is the proposed std::expected (it's not accepted to the standard as far as I know, but there are plenty of non-standard implementations). It allows storing information about the reason for not returning a proper value which similar to what you can do with exceptions.
P.S. Your function appears to be nearly identical to std::find_if. Use standard algorithms when possible. Also consider a data structure that is more efficient for searching if the search space is large.
What is the proper thing for me to return here?
char BCheckString::operator[](int index)
{
if (index < 0 || this->length() <= index)
{
throw IndexOutOfBounds();
???Do I need to return something here???
}
else
{
return ?????;
}
}
I tried return this[index] but VS2013 says: "no suitable conversion function from "BCheckString" to "char" exists. And I have no idea what to return after the throw.
I have:
class BCheckString : public string
{
private:
bool checkBounds();
public:
BCheckString(string initial_string);
char operator[](int index);
class IndexOutOfBounds{};
};
and
BCheckString::BCheckString(string initial_string) : string(initial_string)
{
}
char BCheckString::operator[](int index)
{
if (index < 0 || this->length() <= index)
{
//throw IndexOutOfBounds();
cout << "index out of bounds" << endl;
return 'A';
}
else
{
return 'A';
}
}
Obviously this is homework ;)
While observing that what you're doing here is unnecessary, the syntax is thus:
return string::operator[](index);
You're calling the operator[] of your string parent. This should be preferred to using c_str because string::operator[] does bounds checking in debug builds.
It's also worth noting that .at already does bounds checking in release builds, and throws std::out_of_range.
For the first question, no. After throwing an exception, you don't need to have a return statement. In fact, if you do, the compiler may warn you about "unreachable code".
First, deriving from std::string is not recommended: Why should one not derive from c++ std string class?
As to your questions:
1) After throw you don't return anything.
2) Your attempt to use operator[] is incorrect as you are not calling the parent class's std::string::operator[].
To call the correct operator[]:
else
{
return std::string::operator[](index);
}
this is a pointer, therefore this[index] will erroneously consider this as pointing to an array of instances to access the index-th of them. That will be an instance of the class itself and there's no implicit conversion from that to the declared return type char (this is what the error message is complaining about).
You need to get the char from the base string, and this is done with
return this->string::operator[](index);
If you derived from std::string you can just use c_str() method to access data.
return this->c_str()[index];
I have a function in a C++ program returning a string.
On certain conditions, e.g. if the function encounters an error or so, I want to return a special value telling the caller that something has gone wrong.
I could basically just return an empty string "", but the function does need the empty string as normal return value.
How can I accomplish this?
Do I have do create a special data structure that for my function that holds a bool if the function was successfully run and a string containing the actual return value?
This sounds like a usecase for exceptions.
try {
std::string s = compute();
} catch(ComputeError &e) {
std::cerr << "gone wrong: " << e.what();
}
If you don't want to or can't use exceptions, you could change the function's interface
std::string result;
if(!compute(result)) {
std::cerr << "Error happened!\n";
}
Though most often, i've seen the return value is used for the actual result, and an error pointer is passed
bool b;
std::string s = compute(&b);
if(!b) {
std::cerr << "Error happened!\n";
}
This has the benefit that you can default the error argument pointer to 0 and code that can ignore the error (because it could live with an empty string return, for example, or if it knows in advance the input is valid) would not need to bother:
std::string compute(bool *ok = 0) {
// ... try to compute
// in case of errors...
if(ok) {
*ok = false;
return "";
}
// if it goes fine
if(ok) {
*ok = true;
}
return ...;
}
You can definitely return a pair, although it is klunky.
pair< string, bool > my_method(...) {
if (a) {
return make_pair(some_value, true);
} else {
return make_pair("", false); // error
}
}
pair< string, bool > result = my_method(...);
if (result.second) {
// success
} else {
// error
}
You can also pass either the bool or the string by reference,
bool my_method(string& s, ...) {
...
}
string s;
if (my_method(s, ...)) {
// success
} else {
// error
}
or:
string my_method(bool& ok, ...) {
ok = false; // default
...
}
bool ok;
s = my_method(ok, ...));
if (ok) {
// success
} else {
// error
}
You could try returning an auto_ptr to a string, but this will cost you an explicit new-ing of a string.
std::auto_ptr<std::string> Foo(int i)
{
if(i == 0) // Error!
return std::auto_ptr<std::string>(NULL);
else // Works.
return std::auto_ptr<std::string>(new string("Hello world!"));
}
If it's really something like an error, you should throw an exception. But by reading your question I guess it's not an "exceptional behaviour"?
If that's the case, you have several non-perfect solutions :
Return a structure with the string and a boolean that tells if the function failed (a simple std::pair<> could be enough).
Make your function modify a string parameter provided by reference and return a boolean telling if the function failed.
Make your function a functor/object that have a state. That state would be (at least) a boolean giving the failure or success of the last function call -- that would then be a function call.
3 is IMO bad design, while 2 and 1 are unperfect compromise.
It depends on how is your program organized.
You may return an additional boolean signifying if the function succeeded. You may return a structure containing boolean and string. You may return a special string (not necessarily empty) which should represent the failure. You may throw an exception. You may set a global flag indicating an error (though I would not recommend it).
There must be lot of other methods to express function failure, too.
The std::pair<> method is good. Another alternative is to have the caller pass the output string in as a non-const reference, and have the function return true or false depending on if an error was encountered or not.
bool Foo(int i, std::string& result)
{
bool ret = false; // no error
// do stuff...
result = "blahbalhbalh";
return ret;
}