Modify const parameter reference - c++

Ok so I have two classes that look like:
class Item
{
private:
HANDLE Parent;
public:
Item(const Item &I) = delete;
Item(Item &&I) = delete;
void SetParent(HANDLE Handle);
Item& operator = (const Item &I) = delete;
Item& operator = (Item &&I);
};
void Item::SetParent(HANDLE Handle)
{
this->Parent = Handle;
}
Item& Item::operator = (Item&& I) {/*Do Move Here*/}
class Box
{
private:
HANDLE Handle;
public:
void Add(const Item &I);
};
void Box::Add(const Item &I)
{
I.SetParent(this->Handle); //Error.. Item I is const.
}
I get the error that I is const and that makes sense but I need a way to SetParent of Item I without losing the ability to construct I in place as so:
Box B(Item());
instead of:
Item I;
Box B(I);
Any ideas how I can keep inline construction of I while being able to modify it by calling SetParent?

A solution is to declare the Parent member as mutable and to make the SetParent method constant. A sample code is following and available online
typedef int HANDLE;
class Item
{
private:
mutable HANDLE Parent;
public:
Item(const Item &I) = delete;
Item(Item &&I) = delete;
void SetParent(HANDLE Handle) const;
Item& operator = (const Item &I) = delete;
Item& operator = (Item &&I);
};
void Item::SetParent(HANDLE Handle) const
{
this->Parent = Handle;
}
class Box
{
private:
HANDLE Handle;
public:
void Add(const Item &I);
public:
Box(const Item &I) {
Add(I);
}
};
void Box::Add(const Item &I)
{
I.SetParent(this->Handle); //Error.. Item I is const.
}
int main(void) {
return 0;
}

Related

C++ Signal and Slot not working: slot not responding to event

I am creating a Signal and Slot system with a design like this:
There is the signal and slot classes
struct timeDoubleEvent
{
public:
timeDoubleEvent(const std::string& dataName)
:
dataName(dataName)
{}
const std::string& getDataName() const { return dataName; }
Event<hydraPtr<DataHandler::timeDouble>> update;
void fire(const hydraPtr<DataHandler::timeDouble>& timeDouble) const { update(timeDouble); }
private:
const std::string dataName;
};
class timeDoubleSlot
{
public:
timeDoubleSlot(const std::string& dataName)
:
dataName(dataName)
{}
const std::string& getDataName() const { return dataName; }
virtual void onEvent(const hydraPtr<DataHandler::timeDouble>& timeDouble) = 0;
private:
const std::string dataName;
};
The slot would eventually differ for various cases, so I am creating derived class of it nested inside something:
class BaseClass
{
// forward declaration
class timePriceSlot;
public:
BaseClass(const std::string& name,
const std::vector<hydraPtr<EventHandler::timeDoubleEvent>>& dataEventVector,
const size_t& warmUpLength)
:
name(name),
dataSlotVector(initializeDataSlotVector(dataEventVector)),
warmUpLength(warmUpLength),
dataStorage(initializeDataStorage(dataEventVector)),
timeStorage(initializeTimeStorage(dataEventVector))
{}
private:
const std::vector<hydraPtr<timePriceSlot>> dataSlotVector;
const std::vector<hydraPtr<timePriceSlot>> initializeDataSlotVector(const std::vector<hydraPtr<EventHandler::timeDoubleEvent>>&);
const bool& checkAllDataReceived(const std::string& dataName);
class timePriceSlot : public EventHandler::timeDoubleSlot
{
public:
timePriceSlot(const std::string& dataName,
BaseClass& parent)
:
timeDoubleSlot(dataName),
parent(parent)
{}
void onEvent(const hydraPtr<DataHandler::timeDouble>& timeDouble);
BaseClass& getParent() const { return parent; }
private:
BaseClass& parent;
};
};
(only showing the relevant bits) In particular, the signal-slot connection is done like this:
const std::vector<hydraPtr<BaseClass::timePriceSlot>> BaseClass::initializeDataSlotVector(
const std::vector<hydraPtr<EventHandler::timeDoubleEvent>>& dataEventVector)
{
std::vector<hydraPtr<BaseClass::timePriceSlot>> output(dataEventVector.size());
for (size_t i = 0; i < dataEventVector.size(); ++i)
{
EventHandler::timeDoubleEvent thisTimeDoubleEvent = (*dataEventVector[i]);
std::shared_ptr<BaseClass::timePriceSlot> thisTimePriceSlot = std::make_shared<BaseClass::timePriceSlot>(dataEventVector[i]->getDataName(), *this);
output[i] = thisTimePriceSlot;
thisTimeDoubleEvent.update.connect([&](hydraPtr<DataHandler::timeDouble>& timeDouble) { (*thisTimePriceSlot).onEvent(timeDouble); });
}
return output;
}
I am calling the function with a client program like this:
const std::string stockName = "BBH";
EventHandler::timeDoubleEvent event1(stockName);
std::vector<hydraPtr<EventHandler::timeDoubleEvent>> eventVector(1);
eventVector[0] = std::make_shared<EventHandler::timeDoubleEvent>(stockName);
const hydraPtr<Signal::DerivedClass> myMA = std::make_shared<Signal::DerivedClass>(stockName + "_MA", eventVector, 10);
const std::vector<hydraPtr<DataHandler::PriceTimeSeriesDataStruct>> myData = getAggregatedData();
const std::vector<double> priceVectorCopy = myData[0]->getPriceVector();
std::vector<double>::const_iterator it_d;
const std::vector<std::string> timeVectorCopy = myData[0]->getDateTimeVector();
std::vector<std::string>::const_iterator it_s;
for (it_d = priceVectorCopy.begin(), it_s = timeVectorCopy.begin();
it_d != priceVectorCopy.end(); it_d++, it_s++)
{
const hydraPtr<DataHandler::timeDouble> timeDoubleTemp = std::make_shared<DataHandler::timeDouble>(stockName, (*it_s), (*it_d));
event1.fire(timeDoubleTemp);
}
(DerivedClass is derived from BaseClass, with a different implementation of one function not relevant here) However, I found that even though there is no build or run time error, nothing happens upon the event fire. In fact, the onEvent function is never visited. Have I done something wrong? Thanks in advance.
The problem was in this line
thisTimeDoubleEvent.update.connect([&](hydraPtr<DataHandler::timeDouble>& timeDouble) { (*thisTimePriceSlot).onEvent(timeDouble); });
Both the event and the slot should be pointers, not dereferenced values.

How can I fix this error in this case? "Invalid arguments ' Candidates are: void FreeMemory(std::vector<Element *,std::allocator<Element *>> &) '"?

How can I delete all the pointer in my vector before that I going to copy to my vector new pointers (in case of const object)?
class Element {
int val;
public:
Element(int val) :
val(val) {
}
};
class MyClass {
vector<Element*> v;
static void FreeMemory(vector<Element*>& vec) {
for (unsigned int i = 0; i < vec.size(); i++) {
delete vec[i];
}
}
public:
MyClass() = default;
MyClass(const MyClass& mc) {
//...
}
MyClass& operator=(const MyClass& mc) {
if (this == &mc) {
return *this;
}
//...
FreeMemory(mc.v); //**error** - how can I delete the memory of any Element?
//...
return *this;
}
// ....
// ....
};
binding 'const std::vector' to reference of type 'std::vector&' discards qualifiers
Can I fix it with smart_pointers?
Here is a sketch of a class owning a std::vector of Element objects managed by std::unique_ptr. Not fully worked out, but it might work as a starting point.
class Element {
int val;
public:
explicit Element(int val) : val(val) {}
virtual ~Element() = default;
/* Subclasses must implement this method: */
virtual std::unique_ptr<Element> clone() const = 0;
};
class ExclusivelyOwning {
private:
std::vector<std::unique_ptr<Element>> v;
public:
ExclusivelyOwning() = default;
ExclusivelyOwning(const ExclusivelyOwning& other) {
v.reserve(other.v.size());
for (const auto& element : other.v)
v.push_back(element->clone());
}
ExclusivelyOwning& operator=(const ExclusivelyOwning& rhs) {
/* Use copy-swap idiom, not shown here. */
return *this;
}
ExclusivelyOwning(ExclusivelyOwning&&) = default;
ExclusivelyOwning& operator = (ExclusivelyOwning&&) = default;
~ExclusivelyOwning() = default;
};
Note that copying an object with references to abstract classes (as Element in the code above) requires further techniques to render the copying meaningful. Here, I used a "virtual constructor" - the clone method.

Global std::vector is not retaining data

I have a header...
Components.h
namespace ComponentManager
{
void InitializeComponents(std::size_t numComponents);
void AddComponent(const Component& c, std::size_t position);
std::vector<Component> GetComponents();
}
... and the implementation:
Components.cpp
#include "Components.h"
std::vector<ComponentManager::Component> components;
void ComponentManager::InitializeComponents(std::size_t numComponents)
{
components.resize(numComponents, Component());
}
void ComponentManager::AddComponent(const Component& c, std::size_t pos)
{
components[pos] = c;
}
std::vector<ComponentManager::Component> ComponentManager::GetComponents()
{
return components;
}
In main.cpp, I make sure to initialize the components vector, and I add several components. Upon debugging each AddComponent(...) call, I see that the components are actually stored in the vector. However, when I call GetComponents(), the returned vector is different, as if the components were never stored.
What am I missing?
EDIT: Adding main.cpp (inside main() function)
//Inside EntityManager::Initialize(), I call ComponentManager::InitializeComponents()
EntityManager::Initialize(5000);
for (unsigned int i = 0; i < 10; ++i)
{
uint16_t handle = EntityManager::CreatePlayer(static_cast<float>(i), 50.0f * i);
//Inside EntityManager::AddComponent, I call ComponentManager::AddComponent(..)
EntityManager::AddComponent(handle, ComponentManager::POSITION_COMPONENT | ComponentManager::RENDERABLE_COMPONENT);
}
auto components = ComponentManager::GetComponents(); //this vector does not contain the elements that were added.
Originally, this was the definition of Component:
union Component
{
PositionComponent positionComponent;
VelocityComponent velocityComponent;
AccelerationComponent accelerationComponent;
RenderableComponent renderableComponent;
Component() {}
~Component() {}
Component(const Component& other) {}
Component& operator=(const Component& other)
{
std::memmove(this, &other, sizeof(other));
return *this;
}
};
Adding the definition for the constructor and for the copy constructor was the fix:
union Component
{
PositionComponent positionComponent;
VelocityComponent velocityComponent;
AccelerationComponent accelerationComponent;
RenderableComponent renderableComponent;
Component()
{
std::memset(this, 0, sizeof(Component));
}
~Component() {}
Component(const Component& other)
{
std::memmove(this, &other, sizeof(other));
}
Component& operator=(const Component& other)
{
std::memmove(this, &other, sizeof(other));
return *this;
}
};

operator== of a type erased container

Consider the following class that wraps a container and type-erases its type:
class C final {
struct B {
virtual bool empty() const noexcept = 0;
};
template<class T, class A>
struct D: public B {
// several constructors aimed to
// correctly initialize the underlying container
bool empty() const noexcept override { return v.empty(); }
private:
std::vector<T, A> v;
};
// ...
public:
//...
bool operator==(const C &other) const noexcept {
// ??
// would like to compare the underlying
// container of other.b with the one
// of this->b
}
private:
// initialized somehow
B *b;
};
I'd like to add the operator== to the class C.
Internally, it should simply invoke the same operator on the underlying containers, but I'm stuck on this problem, for I don't know how to do that.
The idea is that two instances of C are equal if the operator== of their underlying containers return true.
Whatever I've tried till now, I ever ended up being unable to get the type of one of the two underlying containers, mainly the one of other.
Is there an easy solution I can't see at the moment or I should give up?
Despite the good suggestion from juanchopanza, I found that, as far as the underlying containers represent the same concept (as an example, different specializations of a vector), maybe there is no need of a type-erased iterator.
Below it's a possible implementation that relies on the operator[] and the size member method:
#include <vector>
#include <cassert>
class Clazz final {
struct BaseContainer {
virtual std::size_t size() const noexcept = 0;
virtual int operator[](std::size_t) const = 0;
virtual void push_back(int) = 0;
};
template<class Allocator>
struct Container: public BaseContainer {
Container(Allocator alloc): v{alloc} { }
std::size_t size() const noexcept override { return v.size(); }
int operator[](std::size_t pos) const override { return v[pos]; }
void push_back(int e) override { v.push_back(e); }
private:
std::vector<int, Allocator> v;
};
public:
template<class Allocator = std::allocator<int>>
Clazz(const Allocator &alloc = Allocator{})
: container{new Container<Allocator>{alloc}} { }
~Clazz() { delete container; }
void push_back(int e) { container->push_back(e); }
bool operator==(const Clazz &other) const noexcept {
const BaseContainer &cont = *container;
const BaseContainer &oCont = *(other.container);
bool ret = (cont.size() == oCont.size());
for(std::vector<int>::size_type i = 0, s = cont.size(); i < s && ret; i++) {
ret = (cont[i] == oCont[i]);
}
return ret;
}
bool operator!=(const Clazz &other) const noexcept {
return !(*this == other);
}
private:
BaseContainer *container;
};
int main() {
Clazz c1{}, c2{}, c3{};
c1.push_back(42);
c2.push_back(42);
assert(c1 == c2);
assert(c1 != c3);
}
Open to criticism, hoping this answer can help other users. :-)
Assuming you wish to return false when the comparing two different containers, this should do the job (caution: untested):
class Container
{
struct Concept
{
virtual ~Concept() = default;
virtual Concept* clone() const = 0;
virtual bool equals(Concept const*) const = 0;
};
template<typename T>
struct Model final : Concept
{
Model(T t) : data{std::move(t)} {}
Model* clone() const override { return new Model{*this}; }
virtual bool equals(Concept const* rhs) const override
{
if (typeid(*this) != typeid(*rhs))
return false;
return data == static_cast<Model const*>(rhs)->data;
}
T data;
};
std::unique_ptr<Concept> object;
public:
template<typename T>
Container(T t) : object(new Model<T>{std::move(t)}) {}
Container(Container const& that) : object{that.object->clone()} {}
Container(Container&& that) = default;
Container& operator=(Container that)
{ object = std::move(that.object); return *this; }
friend bool operator==(Container const& lhs, Container const& rhs)
{ return lhs.object->equals(rhs.object.get()); }
};

C++ cannot instantiate abstract class

I am new to C++. Could you pls help me get rid of the errors:
error C2259: 'MinHeap' : cannot instantiate abstract class
IntelliSense: return type is not identical to nor covariant with return type "const int &" of overridden virtual function function
template <class T> class DataStructure {
public:
virtual ~DataStructure () {}
virtual bool IsEmpty () const = 0;
virtual void Push(const T&) = 0;
virtual const T& Top() const = 0;
virtual void Pop () = 0;
};
class MinHeap : public DataStructure<int>
{
private:
std::vector<int> A;
public:
bool IsEmpty() const
{
..
}
int Top() const
{
..
}
void Push(int item)
{
...
}
void Pop()
{
..
}
};
The problem is with const T& Top() vs. int Top(). The latter is different from the former, and thus not an override. Instead it hides the base class function. You need to return exactly the same as in the base class version: const int& Top() const.
The same problem exists for Push(), BTW.
try
class MinHeap : public DataStructure<int>
{
private:
std::vector<int> A;
public:
bool IsEmpty() const
{
..
}
const int& Top() const
{
..
}
void Push(const int& item)
{
...
}
void Pop()
{
..
}
};
Note that it is using const int& instead of int for Top and Push