Get Array Index from pointer to Array Element?

Right now I am using Slate ListView for an inventory system. List view can only receive TArray<TSharedPtr<FMyClass>> (as far as I know). This way I have a pointer to an Array element but I cant find a way to use this to find the index of the element my pointer points to. Does anyone have any ideas on how I can approach this?

make a for-loop, go through the whole array, compare the content of every index with your pointer, if it matches, save the index and break the loop.

In the end, I used a similar method to this but the problem was that two of the same kind with same attributes would mess up the system. For some reason, testing the memory location didn’t work either and someone suggested subtracting my element pointer with my array pointer but that didn’t work either. Maybe this has something to do with how Smart Pointers work in Unreal? I’ll have to research more on that.

I made a function which assigns an unrepeatable identifier to each object. This way when I use the for loop it always picks the exact element. Thanks for the help.

hm, the TSharedPtr implements the == operator which checks the actual pointers of the internal objects to be equal.


template< class ObjectTypeA, class ObjectTypeB, ESPMode::Type Mode >
FORCEINLINE bool operator==( TSharedPtr< ObjectTypeA, Mode > const& InSharedPtrA, TSharedPtr< ObjectTypeB, Mode > const& InSharedPtrB )
{
	return InSharedPtrA.Get() == InSharedPtrB.Get();
}

So this is a pure “address” check, it shouldn’t matter if your objects are “similar” they have to be the exact same object to evaluate as true.

I did not test it, but theoretically, shouldn’t this work?



TSharedPtr<MyClass> ObjectIWantToFind;
...
int32 IndexIfFound = -1;
TArray<TSharedPtr<MyClass>> LeArray;
...
for( int32 i = 0; i < LeArray.Len(); i++)
{
    if( Poinda == ObjectIWantToFind )
    {
        IndexIfFound = i;
        break;
    }
}

And I didn’t check, but i would have assumed that functionality would be implemented in the TArray class, no?
If two not-same-pointers do a match here, that would be strange, maybe use debugging to get some insight into what the actual adresses are that you are comparing?

Ah, so that is what you meant. I misunderstood you.

The thing is I would not be comparing pointers. I have:
A) My inventory array in my Character. It is a custom struct called FItem.
B) A pointer to the inventory in my HUD class.
C) A TSharedPtr array in my widget class. It is obtained by running a filter function on every item in my inventory array, using the pointer in my HUD. It is not an exact copy of my inventory array because it discards FItems by category.

What I do compare is what my pointer points to with the actual array element.

The SListView takes in a TArray<TSharedPtr<>> and every time I select a row it sends the corresponding element from that array. That way, I get a pointer to the element in my actual inventory array but I can’t compare my FItem to the array pointer. I could however

A) Compare the location of Item to the location of what the pointer points to
B) Create a temporal pointer in the loop and compare both pointers (probably neither would work because the only way I know to point TSharedPtr is using MakeShareable)

Would you mind answering some questions?
A) What is the correct way of pointing smart pointers to a location? What I’ve found tells me to use either


new FWhatevs(MyVariable)
or
MakeShareable(new FWhatevs(MyVariable) //this being the prefered way apparently

This means that if I create two pointers the following way, they would not point to the same location? Testing the following returned false


TSharedPtr<FThing> ptr1 = MakeShareable(new FThing(MyArray[3]));
	
	TSharedPtr<FThing> ptr2 = MakeShareable(new FThing(MyArray[3]));

	bool value = ptr1 == ptr2;

	GEngine->AddOnScreenDebugMessage(1, 2, FColor::Red, value ? TEXT("true"):TEXT("false"));

the following returned true


	TSharedPtr<FThing> ptr1 = MakeShareable(new FThing(MyArray[3]));
	
	TSharedPtr<FThing> ptr2 = ptr1;
	bool value = ptr1 == ptr2;

	GEngine->AddOnScreenDebugMessage(1, 2, FColor::Red, value ? TEXT("true"):TEXT("false"));

I’m a huge C++/overall programming noob :confused: and pointers are new to me. Anyways, my current method works for now as a temporary duct tape solution. I’ll just leave it like that until I have a better understanding of the subject and then come back to it and do it the not lazy way!

Thanks

So, your Inventory is a TArray<FItem*> ?
you can compare the pointer in your inventory array to the actual pointer from the TSharedPtr by comparing
InventoryArrayItemPtr == SharedItemPtr.Get()
that should compare the addresses those both pointers point to, which must be the same, if it is the same object.

I did not use much of shared pointers yet, but from the code it looks like make shareable is the way to go…

The problem in your code examples is that you create a pointer to a NEW FThing (which gets an array element passed to the constructor). So you will end up with TWO DIFFERENT FThings, of course, these pointers are different, they are different objects. If you want to check if the Array element you pass to your FThing are the same, your FThing would need to provide means of getting the contained element to make a comparison of those.

I think I understand it better now after reading your answer and the documentation. Smart pointers can only be used with “new” object, right? If that’s so:

My inventory array is a TArray<FItem>. Meaning that whenever I use MakeShareable to create a new pointer I would lose any way to compare the location with my Inventory since they are different objects. What I could do now though is have a pointer of type FItem in my FItem struct. That way, whenever I access my separate object SharedPtr I get the exact adress of the element in my array. Then I subtract it to the pointer to the first element in my array and I get the index.

That way I can bypass the for loop which might cause problems if I want to search my inventory when it contains lots and lots of other items.