I am using a templated class and creating an array to store values. I need to overload the [] operator in this array and this is where I am having issues.
template <class TYPE>
class ArrayList : public ListInterface<TYPE>
{
public:
TYPE * aL = new TYPE[25];
}
For my overloaded operater for [] I have the following:
TYPE & operator[] (int num) const //will addd throw std out of range
{
return aL[num];
}
However, when I use this operator later in the program it doesn't return the value at that specific index.
void insertAt(int index, const TYPE & newEntry)
//throw (std::out_of_range)...
{
aL[index] = newEntry;
TYPE a = aL[index]; //use this to see what it is returning
}
I used the variable "a" as a debugging tool to see what is returned for aL[index] and I get the following int held inside of "a" : -858993460. I am sure this must be a simple error, I have searched for a very long time to figure out why this behavior is occuring but have not been able to get to the bottom of it. Thanks for the help!
Related
There is a function on BP that looks for an empty slot in the array and fills it. When trying to rewrite it in c++, it throws the error C2678 "binary"==": an operator accepting a left operand of the type "const FSlotStructure" was not found (or there is no acceptable conversion)"
The variables in the picture correspond to the variables in the code. The Find() function itself does not search for the FSlotStructure variable in the Array Inventory array. What is the mistake?
The function below is custom, because "FIND" and "SetArrayElem" functions from UKismetArrayLibrary and could not be used directly.
void UInventoryComponent::CreateStack(FSlotStructure& ContentToAdd)
{
//TArray<FSlotStructure> Inventory;
int32 Index;
for (auto& SlotStructure : Inventory)
{
int32 NewIndex = Inventory.Find(SlotStructure, Index);
Inventory.Insert(ContentToAdd, NewIndex);
}
}
Everything has been resolved, at least the code compiles without errors. All I had to do was add it to FSlotStructure
operator bool() const
{
return true;
}
In my project there is a vector
std::vector<std::shared_ptr<MovingEntity>>gameObjects;
Which I want to delete elements from if they meet the criteria.
Method to delete elements:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(), beeToClose);
bees.erase(q);
}
Method beeToClose:
bool GameWorld::beeToClose( const MovingEntity & bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
if (bee.getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance())
{
return true;
}
return false;
}
When I try to compile the code I get some errors which I tried to understand:
'GameWorld::beeToClose': non-standard syntax; use '&' to create a
pointer
Not sure why this message is given
'std::remove_if': no matching overloaded function found
I did not declare beeToClose right?
'q': cannot be used before it is initialized SDLFramework
q is not initialized because:
std::remove_if(bees.begin(), bees.end(), beeToClose);
does not run correct?
How can I remove a std::shared_ptr correctly from a vector correctly when meeting some criteria?
The syntax for forming a pointer to member function is &ClassName::FunctionName. So you need &GameWorld::beeToClose for a pointer to the beeToClose member function. In your case, you should use a lambda from which you call that function
auto q = std::remove_if(bees.begin(), bees.end(),
[&](shared_ptr<MovingEntity> const& bee){ return beeToClose(bee); });
Also, you're using the wrong vector::erase overload, you want the one that erases a range of elements, not the one that erases a single element.
bees.erase(q, bees.end());
The vector contains std::shared_ptr<MovingEntity> elements, so beeToClose() needs to accept a const std::shared_ptr<MovingEntity> & parameter as input, not a const MovingEntity & parameter. Also, beeToClose() appears to be a non-static class method that accesses a non-static class member (m_beekeeper), so you can't just pass beeToClose() directly to std::remove_if() as it does not have access to the calling object's this pointer, but you can wrap it in a lambda to capture the this pointer.
Try this:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(),
[this](const const std::shared_ptr<MovingEntity> &bee) {
return this->beeToClose(bee);
}
);
bees.erase(q, bees.end());
}
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return (bee->getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance());
}
You might also consider moving the distance calculation into Beekeeper instead:
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return !keeper->isInCatchDistance(bee);
}
bool Beekeeper::isInCatchDistance(const std::shared_ptr<MovingEntity> &bee)
{
return (bee->getConstPosition().distanceTo(getPosition()) <= getCatchDistance());
}
Sorry for the format, I never really posted to a forum like this, so I have to learn the how to a bit.
My problem is:
I'm writing a template class, and I'd like to access my containers via multiple kind of [] operators. I read a bit in this subject, so I've been able to make one overloading, but I need some more:
So in my header file, relevant things about my container:
template <class T>
class version_controlled_vector
{
int rev;
bool vector_state_changed;
std::vector< std::string > revision;
std::vector< std::vector<T> > v;
//first one works ok, im satisfied with it:
std::vector<T>& operator[] (const int idx)
{
return v[idx];
}
//im not sure how to define the further one(s?):
T& operator[](const int idx2) const
{
return v[idx2];
}
//...and ofc some other code
};
//to have these usages at my main.cpp:
version_controlled_vector<int> mi;
version_controlled_vector<std::string> ms;
//this works, and i d like to keep it,
5 == mi[ 0 ][ 0 ];
//and i d like to have these two usages too:
//getting the first character of the stored string:
'H' == ms[ 0 ][ 0 ]; // with the first overload from the header ms[0][0][0]
works to get the first character of the string for eg "Hello"
but, i have to use the ms[0][0] format to achieve this
//and this:
4 == mi[ 0 ]; // i d like this as if it d behave like 4 == mi[0][0];
I don't really get how can I use the single[] when I made an overload to use the [][]
The only solution I have read about is maybe const-overloading, but I'm not sure at all, I'm quite a weakie.
Thanks for ideas!
I think you are muddying the interface of the class. The expectations from the class are:
Get the i-th value from the j-th version.
Get the i-th value from the latest version.
Get the j-th version.
You have the option of using the overloaded operator[] function to get those values but, it will be better to have functions that reflect the interface.
// Get the versionIndex-th version.
std::vector<T>& getVersion(int versionIndex);
// Get the itemIndex-th value from the versionIndex-th version.
T& getItem(int versionIndex, int itemIndex);
// Get the itemIndex-th value from the latest version.
T& getItem(int itemIndex);
Then, the implementation would be simpler and less confusing.
std::vector<T>& getVersion(int versionIndex)
{
// Make sure to add out of bound checks
return v[versinIndex];
}
T& getItem(int versionIndex, int itemIndex)
{
// Make sure to add out of bound checks
return v[versinIndex][itemIndex];
}
T& getItem(int itemIndex);
{
// Make sure to add out of bound checks
return v.back()[itemIndex];
}
Given these, the only operator[] that makes sense, at least to me, is one that returns the i-th value from the latest version.
T& operator[](int itemIndex);
{
// Make sure to add out of bound checks
return v.back()[itemIndex];
}
It's a bit tricky one, you need to realise that when you write
version_controlled_vector<int> mi;
5 == mi[0][0];
during the second fetch you're no longer accessing your version_controlled_vector class but the inner property of it and it's type is std::vector<T> which has its own subscript operator that you call in the second [0].
To control the subscript operator of the second fetch you need to create another class that derives from std::vector<T> and has overloaded subscript operator. Then you should use this class instead of the std::vector in the implementation of version_controlled_vector.
I encountered an issue that I have been trying to solve for some time, and simply couldn't do it. Here is the scenario:
1) I have an Template array class that look something like this
//code taken from http://www.learncpp.com, much appreciation for Alex
#ifndef ARRAY_H
#define ARRAY_H
#include <assert.h> // for assert()
template <typename T>
class Array {
private:
int m_nLength;
T *m_ptData;
public:
Array() {
m_nLength = 0;
m_ptData = 0;
}
Array(int nLength) {
m_ptData= new T[nLength];
m_nLength = nLength;
}
~Array() {
delete[] m_ptData;
}
void Erase() {
delete[] m_ptData;
m_ptData= 0;
m_nLength = 0;
}
T& operator[](int nIndex) {
assert(nIndex >= 0 && nIndex < m_nLength);
return m_ptData[nIndex];
}
int GetLength() { return m_nLength; }
friend ostream& operator<<(ostream& out, const Array<T>& n) {
for(int i=0; i<n.m_nLength; i++) {
if(i) it << "\n";
it << n[i];
}
return it;
}
};
#endif
2) And this is the class I tried making array of and how I did it (it has dynamic memory allocation)
class Tune {
char* artist;
char* song;
public:
explicit Tune(const char* a, const char* s) {
artist = new char [strlen(a)+1]; strcpy(artist, a);
song = new char [strlen(s)+1]; strcpy(song, s);
}
...
#include "Array.h"
void main() {
Array<Tune> tunes(5); //Array of 5 elements
}
error C2512: 'Tune' : no appropriate default constructor available
1> c:\x\x\x\visual studio 2010\projects\x\x\array.h(26) : while
compiling class template member function 'Array<T>::Array(int)'
1> with
1> [
1> T=Tune
1> ]
1> c:\x\x\x\visual studio 2010\projects\x\x\main.cpp(10) : see reference to
class template instantiation 'Array<T>' being compiled
1> with
1> [
1> T=Tune
1> ]
3) Then I remembered that I could solve that issue with something like this (without using my array template class):
void main() {
Tune **tunes = new Tune*[5];
...
}
I would like to know is this the solution and how do I create Array of pointers using my template array class, and second (lest say I have overriden operator<<), how to I print one or all of the elements of the array.
The full program is huge, this is the piece of it. Most of the code is under comments, so the issue is isolated.
I am pretty stuck and this project means a lot to me, but I am an inexperienced programmer so I find it hard to handle issue like this. Thanks for help in advance.
Cheers!
First of all please show the full error message. Secondly it is not clear what is MyType and whether it has the default constructor.
If MyType is for example some arithmetic type then the code below will be compiled without errors.
#include "Array.h"
int main() {
Array<MyType> data(5); //Array of 5 elements
}
At least class Array has the default constructor though it is not used. As for the type MyType then it can be said nothing because you did not show neither the full error message nor the definition of MyType.
I suggest to check whether MyType has the default constructor.
If you want to create an array of pointers then you should write
Array<MyType *> data(5);
As for this code
void main() {
MyType **data = new MyType*[5];
...
}
then it has nothing common with the problem. Take into account that main shall be defined as having return type int.
EDIT: If do not take into account errors in the definition of class Tune, then it has no default constructor. So you should decide whether you want to create an array of obects of type Tune or an array of pointers to objects of type Tune. I already showed how fo define the array of pointers. Or define the default constructor for class Tune.
How do I create an array of pointers using my template Array class?
If your class needs an alternate way of constructing its elements, you should create another constructor that initializes it the way you wish, similar to std::vector's constructor:
Array( int count, const T& value );
The easiest way to implement this would be to declare m_ptData as a double pointer and initialize it like so:
Array( int count, const T& value ) : m_ptData(new T*[count])
{
for (int i = 0; i < count; ++i)
{
m_ptData[i] = new T(value);
}
}
The best (and most difficult) way would be to use placement-new to initialize it, this is how std::vector does it. You can use it like this:
int main()
{
Array<MyType> data(5, MyType("abc")); // Array of 5 elements,
// all initialized to MyType("abc")
}
How do I print one or all of the elements of the array?
The inserter operator<<() should be used to print the entire array, so making it do something like printing only some of the elements would be a bit confusing to maintainers of your code. As alternatives, you can create a stream manipulator if you wish to customize output, or you can use a member function that takes a count of the numbers you would like to print. Also, your class can have begin() and end() functions which return pointers to the beginning and end of the array, so the user of the class can implement the printing at their discretion. In either cases, looping should be used to print the elements.
It is said that the arrow operator is applied recursively. But when I try to execute the following code, it prints gibberish when it is supposed to print 4.
class dummy
{
public:
int *p;
int operator->()
{
return 4;
}
};
class screen
{
public:
dummy *p;
screen(dummy *pp): p(pp){}
dummy* operator->()
{
return p;
}
};
int main()
{
dummy *d = new dummy;
screen s(d);
cout<<s->p;
delete d;
}
What Stanley meant by “recursive” is just that the operator is applied to every returned object until the returned type is a pointer.
Which happens here on the first try: screen::operator -> returns a pointer. Thus this is the last call to an operator -> that the compiler attempts. It then resolves the right-hand sice of the operator (p) by looking up a member in the returned pointee type (dummy) with that name.
Essentially, whenever the compiler finds the syntax aᵢ->b in code, it essentially applies the following algorithm:
Is aᵢ of pointer type? If so, resolve member b of *aᵢ and call (*aᵢ).b.
Else, try to resolve aᵢ::operator ->
On success, set aᵢ₊₁ = aᵢ::operator ->(). Goto 1.
On failure, emit a compile error.
I’m hard-pressed to come up with a short, meaningful example where a chain of operator -> invocations even makes sense. Probably the only real use is when you write a smart pointer class.
However, the following toy example at least compiles and yields a number. But I wouldn’t advise actually writing such code. It breaks encapsulation and makes kittens cry.
#include <iostream>
struct size {
int width;
int height;
size() : width(640), height(480) { }
};
struct metrics {
size s;
size const* operator ->() const {
return &s;
}
};
struct screen {
metrics m;
metrics operator ->() const {
return m;
}
};
int main() {
screen s;
std::cout << s->width << "\n";
}
C++ Primer (5th edition) formulates it as follows on page 570:
The arrow operator never loses its fundamental meaning of member access. When we overload arrow, we change the object from which arrow fetches the specified member. We cannot change the fact that arrow fetches a member.
The deal is once screen::operator->() returns a pointer (dummy*) the recursion stops because built-in (default) -> in used on that pointer. If you want recursion you should return dummy or dummy& from screen::operator->()