I have the following code:
EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
return EdgeSet();
}
and then..
EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());
Because the value does not have to be in the map, I have to somehow account for it, under ideal circumstances, return an empty (new) EdgeSet. I could throw and exception, but is it necessary? This compiles fine under VS (probably already accounts for RVO), but not so with g++.
EdgeSet& Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
static EdgeSet emptySet;
return emptySet;
}
This is just a possible way of doing it: within your Graph class, define an empty member variable of type EdgeSet, with some attribute that identifies it as empty, such as an "mEmptyFlag" boolean:
class Graph {
...
static EdgeSet mEmptyNode(params defining empty node here);
...
}
EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return *(*(it)).second;
}
return Graph::mEmptyNode;
}
callerFunct {
EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());
if (OutcomingEdges.mEmptyflag==true) {
deal with empty node here
} else {
....
}
}
Or even better for encapsulation, hide mEmptyFlag and provide an "IsEmpty()" function for EdgeSet.
Assuming you actually want to return a reference, to allow the caller to modify the returned object, you could return a pointer to the found object, or a null pointer if it's not found:
EdgeSet* Graph::GetNodeOutcomingEdges(long long NodeId) {
//NodeEdgeMap is an unordereded_map
NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
if (it != NodeOutcomingEdges.end()) {
return it->second;
}
return 0;
}
Alternatively, return a boost::optional<EdgeSet&> which can be empty.
But you should not return a reference "just because", you should return a reference if you want the caller to be able to refer to the same object as is stored in the map, and also be able to modify it. Otherwise, returning a copy, or maybe a const-reference, would be better.
NodeEdgeMap::iterator Graph::GetNodeOutcomingEdges(long long NodeId) {
return NodeOutcomingEdges.find(NodeId);
}
Related
What is the idiomatic C++ way of doing this?
I have a method which looks like this:
LargeObject& lookupLargeObject(int id) {
return largeObjects[id];
}
This is wrong, because if you call this with a non-existent id it will create a new instance of large object and put it into the container. I don't want that. I don't want to throw an exception either. I want the return value to signal that object wasn't found (as it is a more or less normal situation).
So my options are either a pointer or an optional. Pointer I understand and like, but it feels like C++ doesn't want to me use pointers any more.
So on to optionals. I will return an optional and then the caller looks like this:
std::optional<LargeObject> oresult = lookupLargeObject(42);
LargeObject result;
if (oresult) {
result = *oresult;
} else {
// deal with it
}
Is this correct? It feels kind of crappy because it seems that I'm creating 2 copies of the LargeObject here? Once when returning the optional and once when extracting it from optional into result. Gotta be a better way?
Since you don't want to return a pointer, but also don't want to throw an exception, and you presumably want reference semantics, the easiest thing to do is to return a std::optional<std::reference_wrapper<LargeObject>>.
The code would look like this:
std::optional<std::reference_wrapper<LargeObject>> lookupLargeObject(int id) {
auto iter = largeObjects.find(id);
if (iter == largeObjects.end()) {
return std::nullopt;
} else {
return std::ref(iter->second);
}
}
With C++17 you can even declare the iter variable inside the if-condition.
Calling the lookup function and using the reference then looks like this (here with variable declaration inside if-condition):
if (auto const lookup_result = lookupLargeObject(42); lookup_result) {
auto& large_object = lookup_result.value().get();
// do something with large_obj
} else {
// deal with it
}
There are two approaches that do not require use of pointers - using a sentinel object, and receiving a reference, instead of returning it.
The first approach relies on designating a special instance of LargeObject an "invalid" one - say, by making a member function called isValid, and returning false for that object. lookupLargeObject would return that object to indicate that the real object was not found:
LargeObject& lookupLargeObject(int id) {
if (largeObjects.find(id) == largeObjects.end()) {
static LargeObject notFound(false);
return notFound;
}
return largeObjects[id];
}
The second approach passes a reference, rather than receiving it back:
bool lookupLargeObject(int id, LargeObject& res) {
if (largeObjects.find(id) == largeObjects.end()) {
return false;
}
res = largeObjects[id];
return true;
}
If default constructed LargeObject is unwanted from lookupLargeObject, regardless of whether it is expensive or it does not make semantic sense, you can use the std:map::at member function.
LargeObject& lookupLargeObject(int id) {
return largeObjects.at(id);
}
If you are willing to live with use of if-else blocks of code in the calling function, I would change the return type of the function to LargeObject*.
LargeObject* lookupLargeObject(int id) {
auto it = largeObjects.find(id);
if ( it == largeObjects.end() )
{
return nullptr;
}
return &(it->second);
}
Then, client code can be:
LargeObject* result = lookupLargeObject(42);
if (result) {
// Use result
} else {
// deal with it
}
I am implementing a member function called CurrentUser. It will take a username as parameter and return the User instance object which matches the given username. Below is the code
User& UserDB::currentUser(string username){
// userlists is a instance member which is list of user objects
for(list<User>::iterator i = userlists.begin(); i != userlists.end(); ++i)
{
if(*i.getName().compare(username)==0){
return *i;
}
}
return null;
}
Not sure if it is the correct way to do so. Correct me if it is wrong. Thanks!
Update:
hey guys thanks for your advice, i figure out a way to do so by returning a User pointer. Here is the code.
User* UserDB::currentUser(string username){
for(list<User>::iterator i = userlists.begin(); i != userlists.end(); ++i)
{
if(i->getName().compare(username)==0){
return i;
}
}
return null;
}
there are a couple of ways to do this cleanly.
You can of course return a pointer, but that will be surprising to people as it is more normal to return a reference or an object. pointers present object consumers with a number of problems, e.g.:
what should I conclude if it's null?
should I delete it?
and so on.
Returning a reference to something or a something removes these ambiguities.
Having said that, references cannot be empty, so the function must return something. If it does not find the item it's looking for, it must indicate that to the caller. One way is an exception (i.e. it was logically incorrect to ask for that item). However, if the item not being there is a normal occurrence, then you don't want to force your consumers to handle exceptions - that's bad form too.
So the answer is to return an object that encapsulates an optional reference.
A good example of this is boost::optional<User&> but if you don't want to include boost it's fairly simple to roll your own:
struct optional_user
{
using element_type = User;
using reference_type = element_type&;
optional_user() : _p(nullptr) {}
optional_user(reference_type r)
: _p(std::addressof(r))
{}
bool valid() const { return bool(_p); }
// compares to true if the user is present, false otherwise
operator bool() const { return valid(); }
reference_type value() const {
assert(_p);
return *_p;
}
// can be used anywhere a User& is required
operator reference_type () const {
return value();
}
private:
element_type* _p = nullptr;
};
now your function becomes:
optional_user UserDB::currentUser(string username)
{
typedef list<User>::iterator Iter;
for(Iter i = userlists.begin(); i != userlists.end(); ++i)
{
if(i->getName().compare(username)==0)
{
return optional_user(*i);
}
}
// return an indicator that the user is not present
return optional_user();
}
and your call site becomes:
optional_user = users.currentUser("bob");
if (optional_user) {
do_something_with(optional_user /* .value() */);
}
If you want to specifically return a reference, the item you are referring to must have a lifetime after execution leaves the function.
There are several alternatives:
static local variable in function
using dynamic memory
variable declared outside function
Pass by non-const reference
Here is an example of #1:
const std::string& Get_Model_Name(void)
{
static const std::string model_name = "Accord";
return model_name;
}
Other alternatives are to return a variable by value (copy). This doesn't use references. A copy is returned.
For example:
std::string Get_Manufacturer_Name(void)
{
return std::string("Honda");
}
You may also consider passing by parameter and modifying the parameter:
void Get_Lunch_Special_Name(std::string& entree_name)
{
entree_name = std::string("Beef Wellington");
}
this is the first time I've done something like this so I'm a little uncertain how I need to do this. I have a very simple class which contains some simple values and some getters:
class Nucleotide{
private:
char Base;
int Position;
int Polymorphic;
public:
Nucleotide(char ch, int pos);
int getPos();
char getBase();
int getPoly();
};
This class is present in another class that contains a vector of them:
class NucleotideSequence{
private:
std::string Name;
std::vector<Nucleotide> Sequence;
public:
NucleotideSequence(std::string name, std::vector<Nucleotide> seq);
std::string getName();
Nucleotide getBase(int pos1);
};
I want the method of the second class called getBase to be able to take a integer - say 1, and return the first Nucleotide object in the vector. What I've written is below:
Nucleotide NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return i; // Return a pointer to the correct base.
}
}
}
I've got Nucleotide as the return type but I was wondering really how I should change this - since if I return nucleotide because of pass by value would it not just return a copy of the object at that place in the vector? So I'd rather return a pointer/reference. I'm using an iterator in the loop so should I just return a pointer with the value of the iterator? How do I do this? In the function I return i but should I be returning i&? I'm uncertain about the specifics - presumably if I'm returning a pointer my return type needs to be Nucleotide* or perhaps Nucleotide& since & means address of? I've thought this through and read Cpp tuts but I'm still slightly unsure of the right answer.
Thanks,
Ben.
You have to return the Nucleotide by reference:
Nucleotide & NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return *i; // Notice the *i instead of i
}
}
}
A reference works very similarly to pointer (allows you to pass the actual object, not its copy), but cannot be null and cannot point to non-existing object, so it's a lot safer than pointer.
Note though, that if you don't find the desired Nucleotide, you don't return anything, what generally is not a good idea. In this case using pointers may actually be a better idea:
Nucleotide * NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return &(*i);
}
}
return nullptr;
}
You don't return a pointer, you attempt to return the iterator. And the function is declared to return an instance and not a pointer. Also, if you don't find the Nucleotide you don't return anything at all leading to undefined behavior if you try to use the "returned" value.
You could change the function to return a pointer, or a reference, or just a by value (copying like it's declared like not.
You can also change so that the function takes the Nucleotide as an argument instead, and then return a boolean indicator if it was found or not.
bool NucleotideSequence::getBase(int pos1, Nucleotide& n)
{
for (...)
{
if (...)
{
n = *i;
return true;
}
}
return false; // Not found
}
As far as your question is concerned, returning a reference (&) as suggested by others is the solution.
In order to improve your code, I would as well suggest a change:
Either go for the operator[], or use the at() present in std::vector.
Thus, you can directly say:
return Sequence[pos1]; or return Sequence.at(pos1);
Your code will benefit from some use of references for efficiency's sake. The getBase method signature should look like this:
const Nucleotide& NucleotideSequence::getBase(int pos1)
The NucleotideSequence constructor signature should look like this:
NucleotideSequence(const std::string& name, const std::vector<Nucleotide>& seq);
And the getName method like this:
const std::string& getName();
(Although return value optimisation might make that less important.)
As for the contents of getBase, it might help understanding to break down the code into:
const Nucleotide* NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); ++i)
{
Nucleotide& ref = *i; //Get a reference to the object this iterator points to
if(pos1 == ref.getPos()) //compare its base to the argument
{
return &ref; // Return a pointer to the correct object.
}
}
return NULL; //or null if we didn't find the object we wanted
}
I am writting a method returning a double*. However, I would like to base another method behavior on output from this method. I would like to have
if (methodReturningArray()==0)
{
this_behavior();
}
else
{
this_other_behavior(methodReturningArray());
}
Is it appropriate then to have methodReturningArray() returning either the 'initialized' or 'build' double* and if this double* could not be appropriately be initialized or build, returning like that
double* new_array ;
return new_array ;
?
In other words, the double* output plays also role of a boolean to check whether some property is completed so that the double* output can be built.
Thanks and regards.
To indicate that something that you return by pointer has not been initialized, use return NULL. And check for it with if(double* d = method()) (or in any other fashion you like).
However, this is not your (or my) grandfathers C++ and you should only write something like this, when you absolutely have reason to do so. I would prefer to return either a std::array or std::vector by value wrapped and throw an exception if the behavior that leads to initialization failure is somehow exceptional. If failing to initialize is part of the idea I'd wrap the return value in a boost::optional. But probably I'd write something that takes an OutputIterator to not force any particular container on my client.
Notes on disaster: double* d; return d will leave your client with a pointer that points to random memory. There is no way for her to figure out if has to be deleted[] or if it is valid. Always initialize your pointers.
Code snippets:
// outputiterator
template<typename OutputIterator>
void myFunc(OutputIterator o) {
// fill stuff in
if(someThing) {
for(int i = 0; i < 5; ++i)
{
*o++ = 23;
}
} else {
// leave it empty
}
}
// client calls like:
std::vector<double> v;
myFunc(std::back_inserter(v));
if(!v.empty()) {
} else {
}
// exception
std::vector<double> myFunc() {
std::vector<double> v;
if(someThing) { v.push_back(23); return v; }
else throw std::runtime_error("Nargh!");
}
// client
try {
auto v = myFunc();
} catch(std::runtime_error err) {
}
// optional
boost::optional<std::vector<double>>
myFunc() {
std::vector<double> v;
if(someThing) { v.push_back(23); return v; }
else return boost::optional< std::vector<double> >();
}
//client
auto v = myFunc();
if(v) {
} else {
}
You got three ways, basically.
1) On error, return NULL. Then you can do boolean checks without issue, and it's sufficient in very most of cases.
2) Return boolean, and handle the double* output using a reference or a pointer argument like this:
bool methodReturningArray(double **out) { *out = ...; return true; }
double *out;
if (!methodReturningArray(&out)) this_other_behavior(out); else ....
3) Throw an exception - IMO kinda convoluted and unuseful.
Returning uninitialized pointer won't allow you to do boolean evaluation on it, and it's dangerous, as such pointer will be assumed dangling pointer afterwards.
I have a function that needs to return NULL in some cases and there is another function that needs to test for the return value of this function. I am aware of boost::optional but am not sure how to use the syntax.
Below would be a simple example of said usage:
int funct1(const string& key) {
// use iterator to look for key in a map
if(iterator == map.end()) {
return NULL // need help here!
else
return it->second;
}
void funct2(string key) {
if(funct1(key) == NULL) { // <-- need help here!
// do something
} else {
// do something else
}
Can someone please help with the syntax?
Thanks.
It stays in the "NULL" state until you set it. You can use this idiom:
optional<int> funct1(const string& key) {
// use iterator to look for key in a map
optional<int> ret;
if (iterator != map.end())
{
ret = it->second;
}
return ret;
}
Then:
if (!funct1(key)) { /* no value */ }
Let me mention a few things before I get to the question.
If the string should always be found (programmer error if it's not) you should probably throw if it can't be instead of using an optional. You may even want to try/catch/throw even if it's user input.
If your class mimics container like semantics, you should consider using an end sentinel to indicate that it wasn't found, not null.
If however returning a null representation is what you're after, your function return type would be boost::optional<int> and the null return would be return boost::none;.
Try this:
int funct1(const string& key)
{
// use iterator to look for key in a map
if(iterator == map.end())
return boost::optional<int>();
else
return boost::optional<int>(it->second);
}
void funct2(string key)
{
const boost::optional<int> result = funct1(key);
if (result.is_initialized())
{
// Value exists (use result.get() to access it)
}
else
{
// Value doesn't exist
}
}
I would also typedef the template, to make things easier:
typedef boost::optional<int> OptionalInt;