How can I refer to what called a function in C++? - c++

I was wondering if there is a way in C++ to know what called a function? Like the this keyword in Java or JavaScript.
For example, I have a function called insert, which inserts an item into a linked list, I want the linked-list that called those the function insert to call two other functions. How would I do that?
I have this right now, is this valid?
bool linked_list::insert( int i )
{
bool inserted = false;
if( this.is_present(i) ) /* function is_present is defined earlier checks if an int is already in the linked-list. */
{
inserted = true // already inside the linked-list
}
else
{
this.Put( 0, i ); /* function Put is defined earlier and puts an int in a linked-list at a given position (first param.). */
inserted = true; // it was put it.
}
return inserted;
}

For historical reasons, this is a pointer. Use -> instead of ..
bool linked_list::insert(int i) {
bool inserted = false;
if(this->is_present(i)) {
inserted = true; // fixed syntax error while I was at it.
} else {
this->put(0, i); // fixed inconsistent naming while I was at it.
inserted = true;
}
return inserted;
}
Usually it is not needed to use this-> at all; you can just do if(is_present(i)).

this works in c++ the same as it does in Java. The only difference is that you need to use this-> instead of this. this is a pointer than therefor you cannot use the dot operator to access it's members.

why don't you just call the other functions in linked_list::insert(int)? And no, it is not valid, you should put this -> something instead of this.something

Related

Setting std::map items as itemdata of CListBox

I have a similar question here but the context of this new question is different.
Background
I have this variable: PublisherMap m_mapPublishers;
The definition of PublisherMap is:
using PublisherMap = std::map<CString, S_DEMO_ENTRY_EX>;
The code
I have this method that reads the map and populates a CListBox:
bool CChristianLifeMinistryPersonalCopiesDlg::InitPublishersGrid()
{
try
{
m_lbPublishers.ResetContent();
for (auto & mapPublisher : m_mapPublishers)
{
bool bInclude = false;
if (m_iDisplayMode == DISPLAY_EVERYONE)
bInclude = true;
else if (m_iDisplayMode == DISPLAY_BROTHER && mapPublisher.second.eGender == GENDER_MALE)
bInclude = true;
else if (m_iDisplayMode == DISPLAY_SISTER && mapPublisher.second.eGender == GENDER_FEMALE)
bInclude = true;
if (bInclude && m_bLimitDisplay)
{
CString strTemp;
if (!m_mapSSAssignedPublishers.Lookup(mapPublisher.first, strTemp))
bInclude = FALSE;
}
if (bInclude)
{
int i = m_lbPublishers.AddString(mapPublisher.first);
m_lbPublishers.SetItemData(i, MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));
}
}
}
catch (_com_error e)
{
LPCTSTR szError = e.ErrorMessage();
AfxMessageBox(szError);
return false;
}
catch (CException* e)
{
e->Delete();
AfxMessageBox(_T("CException"));
return false;
}
m_iSelectMode = SELECT_NONE;
UpdateData(FALSE);
return true;
}
Notice that I use item data:
m_lbPublishers.SetItemData(i,
MAKEWPARAM(mapPublisher.second.eGender, mapPublisher.second.eAppointed));
It works absolutely fine. If I was using a CPtrArray I would have assigned the actual structure object pointers against each entry in the list box.
The question
I don't know the mechanics of std::map enough. Is there any safe way to directly associate each entry from the map (mapPublisher) against each list box entry so that I can later access it?
I realise I could take the text of the list box entry and then find it in the map and get it that way. But if there is a more direct way to tie the two together?
std::map is specified as an associative container that never moves existing elements, see [associative.reqmts]/9:
The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
In practice it's often implemented as a red-black tree.
So it is safe to keep pointers to existing elements, as long as their lifetime exceeds the lifetime of the pointers.
Note you will lose that guarantee if you switch to std::unordered_map (a hash map).
To set:
m_lbPublishers.SetItemDataPtr(i, &mapPublisher.second);
To retrieve:
auto psEntry = (S_DEMO_ENTRY_EX*)m_lbPublishers.GetItemDataPtr(i);
CListBox::GetItemDataPtr() returns void* so a cast is required.
As long as the node of the map isn't destroyed/deleted you can pass a pointer to the mapped datatype directly to the CListBox::SetItemDataPtr.
So in your case accessing the S_DEMO_ENTRY_EX and using a pointer using &mapPublisher.second is OK.
This is guaranteed by the rules for the STL

Iterator over a list pointing to wrong elements

I have 2 variables: std::list lst; and std::list<A*>::iterator lstiter with A being a class. The lst is filled with pointers to the class! B is an other class that holds both variables.
Puts iterator at the begin of the list:
void B::iterstart() {
lstiter = lst.begin();
}
void B::iternext() {
iteratend();
lstiter = ++lstiter;
}
void B::iterprev() {
iteratstart();
lstiter = --lstiter;
}
void B::iteratend() {
if (lst.empty())
throw -1;
if (lstiter == lst.end())
throw "Error: end of list\n";
}
void B::iteratstart() {
if (lst.empty())
throw -1;
if (lstiter == lst.begin())
throw "Error: begin of list\n";
}
(I also have a function that gets the pointer at the element in the list the iterator is pointing too at the moment. Iteratend and iteratstart throw an exception when there are no elements in the list and when I try to go past the last or first element. This is where my problem is!
Now I call: iterstart(); iternext(); iternext(); iternext(); I never get the message!(End of list)
And I do have some other bugs too, Sometimes I call the procedure prev, but I get the return value of the procedure next! (But I want to try to solve the other problem first)
This lstiter = ++lstiter is wrong. With an integer it might work but when used with complicated C++ objects it does not always perform correctly because it depends on the specific implementation of the increment and copy functions. Also, why would you want to do it? All you need is ++lstiter.

What can I use as a NULL struct?

I'd like to code a loop going through several instances of the same struct (named edg in my case) iterated by a certain function going from neighbor to neighbor until it returns an element that says STOP. I tried coding it using a NULL return but it doesn't work. What could I use?
Here is some code explaining it probably more accurately than my previous words:
My structure:
struct edg{
int i,j,k;
edg(int a, int b, int c){
i = a; j = b; k = c; //I'm adding a constructor to it
}
}
My iterating function:
edg neighbour(edg temp){
if(temp satisfies certain criterias){ return edg(new coordinates);}
else{ return NULL;}
}
My loop:
while(my_edg!=NULL){
my_edg = neighbour(my_edg);
}
I guess I could just pick a certain value of an edg define it as a rejection, and replace in my loop by:
while(my_edg!=edg_marked_as_rejection)
But is there another way to do so?
Note that your function:
edg neighbour(edg temp){
if(temp satisfies certain criterias){ return edg(new coordinates); }
else{ return NULL; }
}
returns an instance of edg by value thus trying to return NULL; is invalid (unless you've defined some custom conversion). NULL is a possible value when passing / returning by pointer, which in this case could mean changing the prototype of this function to:
edg* neighbour(edg temp) { ... }
however based on the semantics it would be more reasonable to either pass by reference and return a flag indicating success:
bool neighbour(const edg& temp, edg& result) {
if (...) {
result = ...;
return true;
}
return false;
}
or in case your condition "if(temp satisfies certain criterias)" should be met in most of cases and these criteria not being met is rather an exceptional state, you might also consider throwing an exception (instead of returning NULL).
A third option might be implementing a NULL object design pattern, meaning that instance of edg marked as "invalid" would be constructed and returned and caller would do something like:
edg n = neighbour(tmp);
if (!n.isValid()) {
...
}

I'm trying to create an add function for arrays in c++

This add function will take a single parameter which will be the item to be added to the array. I've tried using a for loop but it didn't work as I expected it to. I'm currently just trying to do something like this:
bool homeworklist::add (homework h)
{
int i = 0;
if(current_size < LIST_MAX){
current_size += 1;
list[i] = h;
++i;
return true;
}
return false;
}
current_size is just a counter.
list is a array that belongs to a homeworklist class
list takes in homework objects.
The function returns true if the object was added succesfully and false if it wasnt added correctly.
The variable i is local, which means each time you call this function, it is initialized to 0, due to this line:
int i = 0;
This in turn means in the subsequent if statement, you are assigning the element to the first location, everytime.
You could make i a class member, just like how you might have declared current_size. Or might be you could just make use of current_size itself.

Does the vector still exists?

I'm having a problem in my c++ game related with the vector.
I want to know if theres any code that tells me if a vector still exists.
Example (x = a structure that I created):
vector<x*> var;
var.push_back(new x);
var[5]->Pos_X = 10;
And now what i want:
delete var[5];
if(var[5] still exists){
var[5]->Pos_X = 20;
}
What could be the code for var[5] still exists?
Unless you've actually set the pointer to null after deleting it, there's no real way to determine whether that slot in the vector contains a pointer to a live object or not.
So you'd need to:
delete vec[5];
vec[5] = NULL;
Then you could test
if (vec[5] == NULL)
to determine if there was "really" something at that location or not.
There is no code for that, not without extra careful work in your deleting process. If you store smart pointers you can do it like this:
vector<unique_ptr<x>> var;
// assuming you actually do add 6 or more elements to the vector
...
var[5].reset();
if (var[5]) { ... }
You could use var.size() to see if the vector contains a pointer at var[5], but that won't tell you whether the pointer is valid.
You could create a small wrapper class:
template <class T>
class wrapper {
bool valid;
T *data_;
public:
wrapper(T *d): data_(d), valid(true) {}
del() { delete data; valid = false; }
bool isValid() { return valid; }
T *data() { return valid ? data : NULL; }
};
std::vector<wrapper<x> > var;
var[5].del();
if (var[5].valid())
var[5].data()->Pos_X = 20;
Personally, I'd prefer to just ensure that all the pointers are valid all the time though.
calling delete you are deallocating memory pointed by that x*, so you still have pointer to some memory address that do not contain anymore what you excpected.
If you want to remove elements from vector consider using "erase"; then, if you don't want to erase but simply "cancel" the Nth element, structure is yours.. put some bool flag inside your structure.