Initializing member variables with a lambda - c++

Suppose I have a template class:
template<class T>
class Entity
{
public:
Entity(std::function<void(T*)> init, int idx) : index(idx)
{
init(data);
}
T* getData(){ return Data; }
private:
int index;
T* data;
};
And I create an instance of the class as so:
Entity<Button> myEnt([](Button* button){
button = new Button();
/* some complex, **unique**, initialization of button */
}, 1);
This will compile, but when I call getData() and attempt to use the pointer returned in some other function the program crashes. I assume its because there is an error where data doesn't get properly initialized, but I cant tell why!
fwiw I can get the program to run as desired if I change the Entity constructor to:
Entity(std::function<T*(void)> init, int idx) : index(idx)
{
data = init();
}
and then call it as so:
Entity<Button> myEnt([](){
Button* button = new Button();
/* some complex, **unique**, initialization of button */
return button;
}, 1);
But in my opinion that's an undesirable way of doing it, and the first method should work, im just missing something.

You are passing data to init() by value, which means the lambda is receiving a copy of data. So any value the lambda assigns to its input parameter will be assigned to the copy and not reflected back to data.
You need to pass data by reference instead, eg:
template<class T>
class Entity
{
public:
Entity(std::function<void(T*&)> init, int idx) : index(idx)
{
init(data);
}
T* getData(){ return data; }
private:
int index;
T* data;
};
Entity<Button> myEnt([](Button* &button){
button = new Button();
/* some complex, **unique**, initialization of button */
}, 1);

If you want to initialize the pointer member, you need a reference or pointer to the member pointer, not the value of the pointer.
template<class T>
class entity
{
public:
Entity(std::function<void(T**)> init, int idx) : index(idx)
{
init(&data);
}
T* getData(){ return data; }
Private:
int index;
T* data;
}
Use it like this:
Entity<Button> myEnt([](Button** button){
// you need a pointer to the pointer in order to initialize it
*button = new Button();
/* some complex, **unique**, initialization of button */
}, 1);

Related

How to map different C++ classes to enum class values

I produce messages and each is receive by one object, chosen by an enum class member:
enum class ReceiverID
{
R1,
R2,
MAX_NUM_RECEIVERS
};
struct Msg
{
ReceiverID _receiverID;
Data _data;
};
The receiving classes are stored in an array. The enum member indexes the array to access the receiving object:
void receive(const Msg& msg)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
if(nullptr == _array[arrIndex])
{
_array[arrIndex] = ??? // How do I associate the enum to the class?
}
_array[arrIndex].processMsg(msg);
}
It is possible the receiving object is missing. If this happens I'd like to use the enum to instantiate the missing object. However, this would require mapping the enum values to the receiving object type.
How can I map a class to each enum? (for all enums).
I'd like to generate a compiler error if a new enum is added but without a corresponding receiver class.
UPDATE
The receiving objects are polymorphic and so have a base class. The array is:
std::array<Base*, MAX_NUM_RECEIVERS> _array;
(removed unique_ptr to simplify question)
For on-the-fly creation of objects we could go for some kind of a factory method, e.g.:
//In the Base class:
static Base* createReceiver(ReceiverID recvID) //static member function
{
switch (recvID)
{
case ReceiverID::R1: return new R1Receiver();
case ReceiverID::R2: return new R2Receiver();
//...
default: throw std::logic_error("Invalid ReceiverID");
}
}
//...
void receive(const Msg& msg) except(true)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
if(nullptr == _array[arrIndex])
{
_array[arrIndex] = Base::createReceiver(msg._receiverID);
}
_array[arrIndex]->processMsg(msg);
}
Instead of having a global std::array<Base*, MAX_NUM_RECEIVERS> _array; and then lazily filling it out on demand, I believe the normal thing to do is make it filled out at construction time:
std::array<Base*, MAX_NUM_RECEIVERS>& _array() {
//use a method to bypass https://stackoverflow.com/questions/1005685/c-static-initialization-order
static std::array<Base*, MAX_NUM_RECEIVERS> array = make_array();
return array;
}
std::array<Base*, MAX_NUM_RECEIVERS> make_array() {
std::array<Base*, MAX_NUM_RECEIVERS> array;
array[static_cast<size_t>(R1)] = &myR1ProcessorObject();
array[static_cast<size_t>(R2)] = &myR2ProcessorObject();
return array;
}
Then your receive method is simple:
void receive(const Msg& msg)
{
const size_t arrIndex = static_cast<size_t>(msg._receiverID);
assert(arrIndex< MAX_NUM_RECEIVERS);
_array()[arrIndex].processMsg(msg);
}

Implement a neutral element in a linked list

I made a bidirectional and 2-dimensional linked list. My nodes are called chunks, and they contain a pointer to the chunks on their left, right, bottom and top.
class chunk;
typedef std::shared_ptr<chunk> chunk_ptr;
typedef std::weak_ptr<chunk> chunk_wptr;
class chunk
{
public:
chunk(wanted_id) : id(wanted_id) {}
chunk_ptr left() const { return _left.lock(); }
chunk_ptr right() const { return _right.lock(); }
chunk_ptr top() const { return _top.lock(); }
chunk_ptr bottom() const { return _bottom.lock(); }
void left(const chunk_ptr set) { _left = set; }
void right(const chunk_ptr set) { _right = set; }
void top(const chunk_ptr set) { _top = set; }
void bottom(const chunk_ptr set) { _bottom = set; }
int id() const { return _id; }
private:
chunk_wptr _left, _right, _top, _bottom;
int _id;
void id(const int id) { _id = id; }
};
Now, let's imagine that I have built the following structure:
If I want to navigate from 1 to 4, I could use the following line of code:
id4 = id1->right()->right()->bottom();
Now let's imagine that chunk 3 has been removed, e.g. id2->right == id4->top == nullptr:
If I want to access id4 then to perform some operation on it, there will be a runtime error. To avoid to perform a check at each step, I would like to introduce a neutral chunk element:
auto null_chunk = std::make_shared<chunk>(-1); // Let's define its id as -1
null_chunk->left(null_chunk);
null_chunk->right(null_chunk);
null_chunk->top(null_chunk);
null_chunk->bottom(null_chunk);
Thus, the following statement would run succesfully:
id4 = id1->right()->right()->bottom();
And then id4 == null_chunk.
However, I'm not quite sure about how to integrate such an element in my code.
I could use a static variable:
// This is a public static method
chunk_ptr chunk::null_chunk()
{
static auto ptr = instanciate_null_chunk();
return ptr;
}
// This is a private static method
chunk_ptr chunk::instanciate_null_chunk()
{
auto ptr = std::make_shared<chunk>(-1);
ptr->left(ptr);
ptr->right(ptr);
ptr->top(ptr);
ptr->bottom(ptr);
return ptr;
}
Now, I would like to initialize left, right, top and bottom by null_chunk in my constructor:
chunk(wanted_id) : id(wanted_id)
{
this->left(null_chunk());
this->right(null_chunk());
this->top(null_chunk());
this->bottom(null_chunk());
}
This leads to a a recursion stack overflow (null_chunk calling the constructor calling null_chunk etc...).
This forces me to define a specific private constructor for null_chunk(), but because I'm using shared pointers, my constructor must be public to use make_shared...
Thus, there is a design flow. What would be the best way to implement such a feature?
One possible to solution to implement the null node is to use a static member. This member is initialized once using another static function, that creates a shared pointer with the null chunk and redirects all outgoing connections to the chunk itself.
On construction of any other chunk all outgoing connections point to the null chunk as well.
As mentioned in the comments above, make sure not to leak any memory due to circular references.
You have to create a second constructor as you mentioned. However using a private struct as argument prevents any calls to this constructor from outside the class.
class chunk {
public:
using chunk_ptr = std::shared_ptr<chunk>;
using chunk_wptr = std::weak_ptr<chunk>;
private:
int _id;
chunk_wptr _left, _right, _top, _bottom;
static chunk_ptr nullchunk;
struct pctor {};
static chunk_ptr gennull() {
chunk_ptr pnullchunk {std::make_shared<chunk>(pctor{})};
pnullchunk->_left = pnullchunk;
pnullchunk->_right = pnullchunk;
pnullchunk->_top = pnullchunk;
pnullchunk->_bottom = pnullchunk;
return pnullchunk;
}
public:
chunk(pctor) : _id(-1) {}
chunk(int id) : _id(id),
_left(chunk::nullchunk),
_right(chunk::nullchunk),
_top(chunk::nullchunk),
_bottom(chunk::nullchunk) {}
bool isNullNode() const
{ return this == chunk::nullchunk.get(); }
//
// Further functions omitted
//
};
chunk::chunk_ptr chunk::nullchunk {chunk::gennull()};

Chained anonymous object creation on the heap

I'm writing some arduino libraries and would like to improve readability / add some syntactic suggar.
What I would like to do is create objects on the heap in a way that would look like:
Panel panel(
Button( 1 ).on( Click( clickfunc ) ),
Button( 2 ).on( Hold( holdfunc, 1000 ) )
);
(Button, Click, Hold are all classes and internally managed via linked lists (so they aren't constant.))
I tried writing it this way but I stumbled over problems with references to temporaries.
Currently I can use:
Button button1( 1 ), button2( 2 );
Click theClick( clickFunction );
Hold theHold( holdFunction, 1000 );
Panel( button1.on( theClick ), button2.on( theHold ) );
but this is not nearly as readable as the above and tends to be error-prone because you have to stay alert and don't put e.g. theClick on another button which would break the linked list.
Some heavily shortened excerpts from the classes like they are now.
class Button {
Handler *_first;
Button( int no ){...}
Button & on( Handler &handler ){
handler._next = _first;
_first = &handler;
return *this;
}
void handle( int oldValue, int newValue ) {
Handler *handler;
for( handler = _first; handler; handler = handler->_next ){
handler->handle( oldValue, newValue );
}
}
}
class Handler {
Handler *_next;
virtual void handle( int oldValue, int newValue ) = 0;
...
}
class Click : public Handler {
...
}
class Hold : public Handler {
...
}
Note that this doesn't necessarily needs to stay this way. The goal is to provide a library where its user doesn't need to know to much about its inner working but has a simple/clean interface.
If you have problem with dangling references with the code above, I suspect you are making a linked list that create references (or pointer) that points to those element on the stack.
I suspect also that your signature looks like this:
Button& on(const Event& event) { /* ... */ }
To help you with your problem, I suggest to change the signature of your on function to something like this:
template<typename EventType>
Button& on(EventType&& event) {
}
That way, you can actually forward the object into the heap, and use some form of type easure to put it into your linked list:
struct Handler {
virtual void handle(int oldValue, int newValue) = 0;
// Defaulted virtual destructor
virtual ~Handler() = default;
};
template<typename T>
struct HandlerImpl : Handler {
// constructors
HandlerImpl(T h) : handler{std::forward<T>(h)} {}
void handle(int oldValue, int newValue) {
handler.handle(oldValue, newValue);
}
// We use the compiler generated destructor
private:
remove_rvalue_reference_t<T> handler;
};
template<typename HandlerType>
Button& on(HandlerType&& event) {
// See the code example below
}
What changes in the rest of your code?
Well, now both syntax you posted are supported. The first syntax will move and hold the variable. The second syntax will only hold references to the events and will assume that the lifetime of the event are equal or bigger of those of the button.
Also, Click and Hold don't need to extend any class nor need virtual function or virtual destructors.
If you don't want the second syntax to hold references and use copy instead, replace remove_rvalue_reference_t by std::remove_reference_t.
This pattern I showed you can be applied for Button, and for any widget type you want.
Here's how remove_rvalue_reference_t is implemented:
template<typename T> struct remove_rvalue_reference { using type = T; };
template<typename T> struct remove_rvalue_reference<T&&> { using type = T; };
template<typename T> using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
Since you have posted an example of your code, I can now help you transform it so it can work with the code above.
First, liked list are slow, and hand rolled liked list are worse. I strongly suggest you to use std::vector. Secondly, std::unique_ptr is the preferred way to hold owning pointers. So, just by following this and the steps mentioned above, your code should look like this:
struct Button {
std::vector<std::unique_ptr<Handler>> _handlers;
Button(int no) { /* ... */ }
// This function will work for any type that
// happen to have an `handle` function.
template<typename H> // <--- H is the handler type
Button& on(H&& handler) { // H&& in this case means forwarding reference.
// We add (emplace) a new HandlerImpl, allocated on the heap using `std::make_unique`
_handlers.emplace_back(
std::make_unique<HandlerImpl<H>>(std::forward<H>(handler))
);
return *this;
}
void handle(int oldValue, int newValue) {
// We use a range for loop here to iterate on the vector
for (auto&& handler : _handlers) {
handler->handle(oldValue, newValue);
}
}
};
// We do not extends anything
struct Click {
// Notice that the function is not virtual
void handle(int oldVal, int newVal) {/* ... */}
};
struct Hold {
void handle(int oldVal, int newVal) {/* ... */}
};
Here's a live example at Coliru

C++ OOP: Class knows its index in the container - prevent overwrite?

I have a class idx_aware that goes into a container container, which wraps around a std::vector. When the class is added to container, container sets a pointer to itself in idx_aware, as well as the index of idx_aware in its internal memory storage.
The index is not going to change until the container is destroyed or idx_aware is removed; idx_aware needs to know about its container and its index, because it has some methods that require both to work.
Now this introduces the following problem: when I get a non-const reference to an idx_aware class contained in container, I could assign to it another idx_aware class, which could have a different index. The intention would be assigning all the fields and keeping the index as it is.
#include <vector>
#include <limits>
#include <iostream>
class container;
// Stores a std::size_t field, which can be set only by subclasses.
class with_idx {
std::size_t _i;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()) {}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) { _i = i; }
};
// Knows its index and its container
class idx_aware : public with_idx {
container const *_container;
int _some_field1;
float _some_field2;
public:
void foo() {
// Do stuff using _container and _i
}
private:
friend class container;
};
// Wraps around a std::vector
class container {
std::vector<idx_aware> _data;
public:
idx_aware &operator[](std::size_t idx) {
// Need non-const access to call foo
return _data[idx];
}
idx_aware const &operator[](std::size_t idx) const {
return _data[idx];
}
std::size_t add(idx_aware const &item) {
// Here it could potentially reuse a freed position
std::size_t free_slot = _data.size();
// Ensure _data is big enough to contain free_slot
if (_data.size() <= free_slot) {
_data.resize(free_slot + 1);
}
// Assign
_data[free_slot] = item;
_data[free_slot].set_idx(free_slot);
_data[free_slot]._container = this;
return free_slot;
}
};
int main() {
container c;
idx_aware an_item;
std::size_t i = c.add(an_item);
std::cout << c[i] << std::endl; // Prints 0
idx_aware another_item; // Created from somewhere else
// I want to set all the data in idx_aware, but the
// index should stay the same!
c[i] = another_item;
std::cout << c[i] << std::endl; // Prints numeric_limits<size_t>::max()
// Now container[i] is broken because it doesn't know anymore its index.
return 0;
}
One possible workaround would be to change with_idx in such a way that when set_idx is called, a flag is set that prevents assignment and copy operator to overwrite the _i property, like this:
class with_idx {
std::size_t _i;
bool _readonly;
public:
with_idx() : _i(std::numeric_limits<std::size_t>::max()), _readonly(false) {}
with_idx(with_idx const &other) : _i(other._i), _readonly(false) {}
with_idx &operator=(with_idx const &other) {
if (!_readonly) {
_i = other._i;
}
return *this;
}
operator std::size_t() const { return _i; }
protected:
void set_idx(std::size_t i) {
_i = i;
if (i != std::numeric_limits<std::size_t>::max()) {
// This has been set by someone with the right to do so,
// prevent overwriting
_readonly = true;
} else {
// Removed from the container, allow overwriting
_readonly = false;
}
}
};
This would have the consequence of returning, after assignment, a reference to an idx_aware class with unchanged index.
idx_aware &not_in_container1 = /* ... */;
idx_aware &not_in_container2 = /* ... */;
idx_aware &in_container = /* ... */;
not_in_container1 = in_container = not_in_container2;
// std::size_t(not_in_container_1) != std::size_t(not_in_container_2)
Is there a design pattern that can model this situation in a better way? My searches were not successful.
Are there other unwanted consequences of overriding the assignment operator in this way? The limitation I pointed out in the previous example does not look too "bad".
Is there an easier solution? I thought about writing some proxy object to replace the idx_aware & return type of operator[].
Experience tells that when C++ does not do what you intend, you are likely to be misusing OOP...
Robert's comment suggested me this solution.
Why would the contained object know about its container? To be able to perform actions such as foo and provide shorthand methods that otherwise would require to have access to the container.
Let's take this functionality away from the contained object; the contained object is just data payload. Instead, let's make operator[] return not the contained object, but some sort of iterator, a wrapper around the contained object, which knows the container and the index, and once dereferenced returns the actual contained object.
class was_idx_aware {
int _some_field1;
float _some_field2;
};
class container {
std::vector<idx_aware> _data;
public:
class idx_aware_wrapper {
container const *_container;
std::size_t _idx;
public:
idx_aware_wrapper(container const &c, std::size_t i)
: _container(&c)
, _idx(i)
{}
was_idx_aware const &operator*() const {
return _container->_data[_idx];
}
was_idx_aware &operator*() {
return _container->_data[_idx];
}
void foo() {
// Do stuff using _container and _idx.
}
};
idx_aware_wrapper operator[](std::size_t i) {
return idx_aware_wrapper(*this, i);
}
/* .... */
};
This allows quick access to any data in was_idx_aware, and the wrapper class can be augmented with all the methods that require interaction with the container. No need to store and keep indices up to date or override assignment operators.

copy local objects by reference

Here's my problem,
Class MClass {
public:
void Add(OtherClass* objects) {
_objects = objects;
}
private:
OtherClass* _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
OtherClass obj[NUMBER_OF_OBJECTS];
//obj initialization here
//...
myObj.Add(obj);
}
It will cause a RT error because the *obj diminishes after the end of the function body.
But, how can make this one valid?
I like to initialized first an object before assigning it to other class.
EDIT
I don't want to use storage classes or something here, I just want a raw array since it is very expensive for me to use. Its functionality will not lessen my problem here.
So how do I do that in a raw-array style?
Class MClass {
public:
void Add(std::vector<OtherClass> objects) {
_objects = std::move(objects);
}
private:
std::vector<OtherClass> _objects;
}
//otherfile.cpp
void Setup() {
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
myObj.Add(std::move(obj));
}
In your example, you store a pointer to a local array. If the method ends, the array goes out of scope and doesn't exist anymore.
This is the reason, your pointer is not valid anymore. If you want to solve this, learn about the scope of variables in C++.
It is not completely clear what you are trying to do, but you could store a collection of objects instead of a pointer:
class MClass
{
public:
void Add(const std::vector<OtherClass>& objects) {
objects_ = objects;
}
void Add(std::vector<OtherClass>&& objects) {
objects_ = std::move(objects);
}
private:
std::vector<OtherClass> objects_;
};
then
void Setup()
{
MClass myObj;
std::vector<OtherClass> obj(NUMBER_OF_OBJECTS);
//obj initialization here
//...
myObj.Add(std::move(obj)); // move obj's contents onto myObs's objects.
}
Stop using raw arrays, and use either std::vector or std::array. Then you don't have to worry about it anymore.
If you really want to do it manually, you have to copy is manually as well. Using e.g. std::vector and std::move is more effective, but here you go:
Class MClass {
public:
MClass()
: _objects(nullptr), _count(0)
{}
MClass(const MClass& other)
: _objects(nullptr), _count(0)
{
Add(other._objects, other._count);
}
~MClass()
{
if (_objects != nullptr)
delete [] _objects;
}
void Add(const OtherClass* objects, const size_t count)
{
if (_objects != nullptr)
delete [] _objects;
_objects = new [count];
for (size_t i = 0; i < count; i++)
_objects[i] = objects[i];
_count = count;
}
MClass& operator=(const MClass& other)
{
Add(other._objects, other._count);
}
private:
OtherClass* _objects;
size_t _count;
};
// ...
myObj.Add(obj, NUMBER_OF_OBJECTS);
As you can see, it's a lot of more code, which makes it harder to follow and debug, and also larger possibility of errors. And not as "effective" as I said above.