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'm using a class
class list
{
int val;
list *next;
}
I want to overload the [] operator. This is what i've come up with:
int & operator [](int n)
{
list *p;
p=this;
for(int i=0; i<n; i++)
{
p=p->next;
if(p==NULL)
{
cout<<"Index out of range ";
return ?? ;
}
}
return p->val;
}
I'm interested to know if there is a way to return nothing in case the index is out of range since the type of the value returned is int&.
If the "index is out of range", this indicates a major internal logic problem in the code.
For this situation, in C++ you can throw an exception, to indicate an exceptional situation. Although there is a certain school of thought that frowns upon use of exceptions, they are a key part of C++, and there's nothing wrong with using exceptions, where appropriate.
If, on the other hand, your application does not consider an index out of range to be an internal logical fault, and it might very well be an expected error condition that should be handled normally, one way to handle this would be for your operator[] to return a utility object that has a boolean flag or a suitably named function such as error() and an operator int() overload. Thusly, the users of operator[] are now responsible for figuring out how to handle the error condition.
Possible options:
use http://en.cppreference.com/w/cpp/utility/optional - probably most elegant and modern-cpp-way
prepare "empty object" as static member of your class and return
reference to it (you can also return return pair with object and boolean variable with information if result is correct )
return pointer to element and nullptr when no
result (reather bad option)
I'm overloading the subscript operator for the first time and I'm having troubles in returning a reference value.
I followed the rules of thumb from a post in c++faq tag, but there's something I'm missing.
const T& operator[](int index) const {
if ((index < 0) || (index > size)) {
// provide exception handling for this error
std::cout << "Error! Index out of bound." << std::endl;
std::exit(0);
} else {
Block* b = head;
while (b) {
if (b->position == index)
return *b->data;
b = b->next;
}
}
}
I implemented them in both variants: with const return value and const function (as above), and without (that is identical except for the two const keywords).
The problem is that when I run the test main, it simply crashes. I thought that the bug was in the return *b->data; statement, but I can't figure neither which it could be nor if I'm wrong and there are other errors.
Any ideas?
Thanks in advance.
If you want to return a reference on data, I'm not sure if it's what you want, you to return a reference of type T and I'm assuming data is of type T, it should be something like:
return b->data;
Else, you are returning a reference on the adress of data.
EDIT: Corrected a mistake
I like the feature in Python that can return None when it doesn't find the correct return value. For example:
def get(self, key):
if key in self.db:
return self.db[key]
return None
I need to implement the same feature in C++. I think about some possibilities.
Return true/false, when true get the value from reference or pointer
bool get(string key, int& result)
{
if (in(key, db)) {
result = db[key];
return true;
}
return false;
}
Throw an error for notifying None case
int get(string key) throw (int)
{
if (in(key, db)) {
result = db[key];
return result;
}
throw 0;
}
try {
....
}
catch (int n)
{
cout << "None";
}
Use pair
pair<bool, int> getp(int i)
{
if (...) {
return pair<bool, int>(true, 10);
}
return pair<bool,int>(false, 20);
}
pair<bool, int> res = getp(10);
if (res.first) {
cout << res.second;
}
Which one is normally used in C++? Are there any other ways to do it in C++?
The normal C++ way to do this (note: C++ is not Python) is to return iterators from such functions and return end() when the item can't be found.
If you wish to use non-iterator return values however, use boost::optional and return boost::none when you would return Python's None.
Definitely don't use throw unless you expect to never have the error case during normal execution.
I achieved the good/bad return value using a small custom Checked templated class.
My actual class was a little more comprehensive, including assignment operators, error reason strings and specialisations for reference types, et cetera, which is why I didn't use boost::optional<T>. I could publish the full class if there is interest.
The general gist of the class is this:
static const class Bad {} None;
template<typename ValueType>
class Checked
{
public:
// Constructor for good value.
Checked(ValueType x)
: value(x), valid(true)
{}
// Constructor for bad value.
Checked(Bad)
: value(), valid(false)
{}
operator ValueType(void) const
{
if (!valid)
;//assert or throw...
return value;
}
ValueType value;
bool valid;
};
This can be used like so:
Checked<int> Divide(int numerator, int denominator)
{
if (denominator == 0)
return Bad(); // or None;
return numerator / denominator; // Automatically uses the "good value" constructor
}
or:
Checked<int> result = Divide(4, 5);
if (result.valid)
std::cout << result; // or result.value
else
std::cout << "Bad!";
This approach is often more efficient than the reference approach because of return value optimisation.
I think different projects in C++ use different standards, but Return true/false you mentioned could be the most common way in C++, although some people prefer to return false on success while the others return true on success. In other cases, if the value you would like to get is a pointer, then returning null is another common way in C++.
For example, if you're working on Microsoft related projects, then the most common way is to return HRESULT, which is a return type introduced by Microsoft.
In linux, functions usually return 0 on success, and non-zero value indicates error code.
(you may find this discussion helpful).
I would say that those three methods are all very common in C++.
It goes without saying that if the return type already can have some sort of "invalid" or "zombie" state (e.g., like a NULL pointer or a NaN number), then that might just be the easiest thing to use.
The "take output-parameter by reference and return an error-code" is the more traditional C-style way of doing things, which is, of course, very common. The tradition is to return 0 on success and some error-code on failure (any non-zero value).
The "throw an exception if you can't return a value" generally makes sense if you adopt exceptions in your code. This is very common, but not universally accepted (not everyone likes or uses exceptions for the same purposes).
Those first two options are in a never-ending feud (i.e., error-codes vs. exceptions), and it really depends on which side you pick. So, I would refer you to that debate (which is too subjective for StackOverflow, of course).
The "return a pair of bool and value" is, I would say, less common, but still I've seen this many times. With the adoption of tuples (boost::tuple or std::tuple (C++11)) and with the use of tiers (boost::tie or std::tie (C++11)), the whole idea of returning multiple values from a function (like many languages allow) is ever more attractive and used in practice.
Among other options, you have boost::optional<T>, whose name is pretty self-explanatory (basically, the third option (pair) wrapped in a prettier package). And you might also have Alexandrescu's Expected template, which gives you a hybrid of all three options such that you get a return value bundled with a flag to know if it is valid or not, and bundled with an exception describing why it couldn't produce the value, which would be automatically thrown if you attempt to read the invalid value. However, the template requires C++11 features to work.
When returning pointer, I can use reinterpret_cast for NULL return.
class A
{
};
A* a(int i)
{
if (i == 0) return new A();
return reinterpret_cast<A*>(NULL);
}
int main(int argc, char *argv[]) {
A* result = a(1); // result is NULL
if (result == NULL) {
cout << "NULL returned";
}
result = a(0);
if (result != NULL) {
cout << "NON NULL returned";
}
}
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.