I would like some explanation as to what a part of this function does:
bool Compare(CBox* pBox) const
{
if (!pBox)
return 0;
return this->Volume() > pBox->Volume();
}
What does if(!pBox) check for? Is that if statement necessary?
if (!pBox) checks if the pointer pBox is null. It is necessary since you are calling a function (Volume()).
The IF is testing for null, if it is true (not zero), it ensure a zero being returned. It is necessary since you are comparing an instantiated object (you are calling its method) against another and this last can be null.
Related
I know that in order to mock how a method responds, you have to use
every { instanceX.methodB() } returns "42"
I'm trying to mock an iterator, for which you have to mock 2 methods hasNext() and next(), if hasNext() returns true always there will be an infinite loop, if it returns false from the beginning, next() will not return anything.
My question is: is there a way to mock individual calls one by one with mockk, as you can do in mockito ? I couldn't find anything in the docs.
At the excellent post Mocking is not rocket science are documented two alternatives:
returnsMany specify a number of values that are used one by one i.e. first matched call returns first element, second returns second element:
every { mock1.call(5) } returnsMany listOf(1, 2, 3)
You can achieve the same using andThen construct:
every { mock1.call(5) } returns 1 andThen 2 andThen 3
Use returnsMany or andThen construct with/instead of return.
Now I have a similar use-case, but for me answers is the appropriate solution as I already have an Iterator in place (and the returned iterator is actually a custom extension of Iterator):
every { mock.bogusIterator() /* : CustomIterator */ } answers {
val testIterator = testList.iterator() // just an Iterator
every { hasNext() } answers { testIterator.hasNext() }
every { next() } answers { testIterator.next() }
}
where testList contains some predefined values for the test.
returns always returns the value that is given to the function at that time. So using every { hasNext() } returns whatever will always return the value of whatever at that mock declaration time, regardless of whether whatever is mutable or not. On the other hand, with answer you always get the current value of what you return at the time of calling the function. In case someone gets confused by it ;-) Maybe also my further explanation confuses a bit :-)
I couldn’t answer the #GACy20, so I’m putting the answer to his question here.
Doubt: How does this apply if I want the first call to throw an exception and the second call to return a value?
You just need to do this:
every { thing.save(any()) } throws RuntimeException("Erro") andThen aRealValue
I often use -1 as the invalid value type when returning from a function, where the input yields incorrect output. For instance, writing an indexing function where the index is out of bounds, instead of throwing an exception, -1 can be returned. But when writing a function that has negative values as possible return types, this technique does not work. What is the correct way to return an invalid type value in such instances?
The technique I use mostly is to set the return type to be of type *int, and return a Pointer to NULL. But, that requires all return values to be of a pointer type, which seems like an extra overhead to the function. Is there an accepted standard for returning values in such cases?
In newer C++, I'd suggest using std::optional<>; if you don't yet have it, boost::optional<>.
One option would be to let your function take a bool& as an output parameter used to indicate if the returned value is valid.
int myFunc(bool& valid); // sets 'valid' to true if result is usable, false otherwise
Users can then do
bool valid = false;
Int result = myFunc(valid);
if (!valid) {
// Handle error
}
// Use result
Not the most pretty solution, but it does the job.
Apart from the answer I provided above, there's a very clean, continuation-passing solution (given you're non-virtual):
template<typename Success, typename Failed>
void parse( const std::string& str, Success s, Failed f )
{
auto a = start_parse(str);
if( a.problem() )
return f(); // you _might_ have an error code here
s( finish_parse(str, a) );
}
Then you might customize by:
Success:
[&i] (int i_) { i = i_; }
out(i), where out(int& output_) returns the above lambda for output_
actual code doing something useful
function to continue with
Failed:
[&i]{ i = 0; }, `[&i]{ i = nullopt; }, or any other default value
[] { throw MyFavouriteException(); }
retry logic
std::terminate()
[]{} if you don't care (or if you're 100% sure it'll succeed)
It might look a little verbose, but IMHO:
it's trivial to read
any other schematics can be mimicked, even if there's no default c'tor
easy to change as well
'you don't pay for what you don't use', can surely be optimized away
every schematic is visible and apparent from code:
for default value, caller sets it, not callee or global
std::optional<> and default value are handled the same
for exception, caller knows better what to throw
for no action, you don't have to lookup the implementation to know this
for std::terminate(), well, you know what to expect
if you 'speak' CPS, you might actually continue and save an if / catch / etc.
The only issue I see is constructor initializer lists. Any thoughts on this?
I was working on some c++ code like this:
//c++ code
class MovieInfo;
MovieInfo getMovieInfoByName(String movieName)
{
//search the movieInfoList with movieName
if(FOUND)
return movieInfo;
//TODO: **what should i return if the movieInfo can't be found in the list?**
}
The question is what should i return if the movieInfo can't be found in the list?
You have several options:
Define the MovieInfo class such that an "invalid" instance is possible (similarly to how a default-constructed std::thread doesn't represent an actual thread) and return such an instance.
Make it a precondition of getMovieInfoByName() that the name corresponds to a valid movie info, and simply return a random value if it doesn't (as "violating preconditions leads to undefined behaviour").
Throw an exception when the name is not found.
Return something like boost::optional<MovieInfo>.
Give getMovieInfoByName() an extra parameter of type MovieInfo which would be used as the return value in case no match for the name is found.
It all depends on your intended use of the function.
It depends on the context and preconditions that must be met. For example if you are not sure whether the list contains such a movie by the time you call it, then it would be reasonable to do:
bool getMovieInfoByName(const std::string& movieName, MovieInfo& movieInfo)
{
...
if (FOUND) {
movieInfo = ...;
return true;
}
return false;
}
since the caller will most likely have to know whether the movie with such a movie exists or not.
If it shouldn't happen that getMovieInfoByName will not find the movie, i.e. the caller should already know whether the list contains such a movie by other means, then it is perfectly reasonable to throw an exception since it is exceptional state and rather indicates the wrong usage of this method.
There's also a design pattern called Null Object, which is based on constructing an object, state of which can indicate whether it is a valid / initialized object or it is a dummy instance representing NULL.
In this case the caller would most likely still have to check whether appropriate MovieInfo instance has been returned and this class should provide a method such as bool isValid();.
Introduction: I got a function doing some work and returning a bool. The bool should be false, if some error occured. So I could use the bool, if I want to check for errors. But what, if I am completely sure (I know, you can never be completely sure, but maybe you understand what I mean) that there will be no error in this part or you just don't care if there is because it has no influence.
Question: Will there occure some memory leak or other performance issue if I just not 'catch' the returned bool?
minimum Codeexampe:
bool my_func(/*some variables*/)
{
if(/*error-condition*/)
{
//do something
return false;
}
else if(/*other error-condition*/)
{
//do something
return false;
}
return true;
}
int main(void)
{
my_func(/*variables*/);
return 0;
}
Comment: that will not return any compiling or runtime errors or unhandled exceptions
You can safely ignore the return value of a function if it is not a pointer to memory that was allocated from within the function and not freed within that function.
In C++ memory can only leak for objects with dynamic storage duration, that is, objects allocated with new or std::malloc (cmp. C++11 3.7.4/1)
The bool in your function will be a temporary, or in other words, it has automatic storage duration (cmp. C++11 3.7.3/1), so it is perfectly fine to ignore that.
Function return values can always be ignored unless they tell you information about resources that a function has consumed and not released; e.g.
1) A pointer or a structure containing pointers to memory allocated by the function
2) A pointer or a structure containing pointers to files / stream buffers opened by the function
You should always check the function documentation before choosing to ignore a return value.
No, there will be no performance loss or memory leak.
However, in general exceptions are the proper way of handling errors in C++.
No, it is a void statement, the bool is discarded
You can feel free to ignore it as the return value just doesn't gets used.
It is just a void statement this would be at all the same as writing 2; or identifiername; In your code.
It would get invoked, but as you aren't storing the value, nothing else will happen.
I'm currently learning C++ and practicing my Knowledge by implementing an simple AddressBook Application. I started with an Entry class and an AddressBook class which implements a STL Map to access the entries by the last names of the persons. Now I arrived at the following code:
Entry AddressBook::get_by_last_name(string last_name){
if(this->addr_map.count(last_name) != 0){
//What can I do here?
} else {
return addr_map[last_name];
}
In Scripting Languages I would just return something like -1, Error Message(A List in Python) to indicate that the Function failed. I don't want throw an exception, because it's part of the application logic. The Calling Class should be able to react to the request by printing something on the console or opening a Message Box. Now I thought about implementing the Scripting Languae Approach in C++ by introducing some kind of an Invalid State to the Class Entry. But isn't that bad practice in C++? Could it be that my whole class design is just not appropriate? I appreciate any help. Please keep in mind that I'm still learning C++.
Some quick notes about your code:
if(this->addr_map.count(last_name) != 0){
//What can I do here?
You probably wanted it the other way:
if(this->addr_map.count(last_name) == 0){
//handle error
But your real problem lies here:
return addr_map[last_name];
Two things to note here:
The operator[] for map can do 2 things: If the element exists, it returns it; If the element doesn't exist, it creaets a new (key,value) pair with the specified key and value's default constructor. Probably not what you wanted. However, if your if statement from before would have been the right way, then the latter would never happen because we would knowthe key exists before hand.
In calling count() before, you effectively tell map to try and find the element. By calling operator[], you are telling map to find it again. So, you're doing twice the work to retrieve a single value.
A better (faster) way to do this involves iterators, and the find method:
YourMap::iterator it = addr_map.find(last_name); //find the element (once)
if (it == addr_map.end()) //element not found
{
//handle error
}
return *it.second; //return element
Now, back to the problem at hand. What to do if last_name is not found?
As other answers noted:
Simplest solution would be to return a pointer (NULL if not found)
Use boost::optional.
Simply return the YourMap::iterator but it seems that you are trying to "hide" the map from the user of AddressBook so that's probably a bad idea.
throw an exception. But wait, now you'll have to first check that calling this method is 'safe' (or handle the exception when appropriate). This check requires a boolean method like lastNameExists which would have to be called before calling get_by_last_name. Of course then we'er back to square 1. We're performing 2 find operations to retrieve a single value. It's safe, but if you're doing A LOT of calls to get_by_last_name then this is potentially a good place to optimize with a different solution (besides, arguably the exception is not very constructive: What's wrong with searching for something that isn't there, huh?).
Create a dummy member for Entryindicating that is not a real Entry but that is very poor design (unmanageable, counter intuitive, wasteful - you name it).
As you can see, the first 2 solutions are by far preferable.
One dead-simple option is to change the return type to Entry* (or const Entry*) and then return either the address of the Entry if found, or NULL if not.
If you use Boost, you could return a boost::optional<Entry>, in which case your success code would be the same, but on not-found you'd say return boost::none. This is fancier, but does about the same thing as using a pointer return type.
Throwing an exception is definitely the 'correct' C++ thing to do, based on your function return type.
You might want a function like this to help you, though:
bool AddressBook::lastNameExists(const string &last_name)
{
return addr_map.count(last_name) > 0;
}
Note that your current code returns the entry 'by value' so modifying the returned entry won't update the map. Not sure if this is by accident or design...
Other answers have given various approaches, most of them valid. I didn't see this one yet:
You could add a second parameter with a default value:
Entry AddressBook::get_by_last_name(string last_name, const Entry& default_value){
if(this->addr_map.count(last_name) == 0){
return default_value;
} else {
return addr_map[last_name];
}
In this particular instance, there might not be a sensible default value for a non-existing last name, but in many situations there is.
In C++ you have several ways of signalling that an issue happened in your function.
You can return a special value which the calling code will recognize as an invalid value. This can be a NULL pointer if the function should return a pointer, or a negative value if your function returns an index in an array, or, in the case of a custom class (e.g. your Entry class) you can define a special Entry::invalid value or something similar that can be detected by the calling function.
Your calling code could look like
if ( entryInstance->get_by_last_name("foobar") != Entry::invalid)
{
// here goes the code for the case where the name is valid
} else {
// here goes the code for the case where the name is invalid
}
On the other hand you can use the C++ exceptions mechanism and make your function throw an exception. For this youcan create your own exception class (or use one defined in the standard library, deriving from std::exception). Your function will throw the exception and your calling code will have to catch it with a try...catch statement.
try
{
entryInstance->get_by_last_name("foobar")
}
catch (Exception e)
{
// here goes the code for the case where the name is invalid
}
// here goes the code for the case where the name is valid
Apart from the fact that you could have more than one entry per surname.
Eliminate the getter, and you've solved the problem, or at least shifted it elsewhere.
Tell the AddressBook to display people with given surnames. If there aren't any it can do nothing.
AddressBookRenderer renderer;
AddressBook contacts;
contacts.renderSurnames("smith", renderer);
contacts.renderCompletions("sm", renderer);
//etc
You can do what std::map (and the other containers do).
You return an iterator from your search function.
If the search does not find a value that is useful return an iterator to end().
class AddressBook
{
typedef <Your Container Type> Container;
public:
typedef Container::iterator iterator;
iterator get_by_last_name(std::string const& lastName) {return addr_map.find[lastName];}
iterator end() {return addr_map.end();}
};
Your address book is a container like object.
Not finding an item in a search is likely to happen but it does not have enough context to incorporate error handling code (As the address book could be used from lots of places and each place would have different error handling ideas).
So you must move the test for not found state out of your address book.
just like "Python" we return a marker. In C++ this is usually an iterator to end() which the calling code can check and take the appropriate action.
AddressBook& ab = getAddressBookRef();
AddressBook::iterator find = ab.get_by_last_name("cpp_hobbyist");
if (find != ab.end())
{
Entity& person *find; // Here you have a reference to your entity.
// you can now manipulate as you want.
}
else
{
// Display appropriate error message
}