I've just been doing some experimenting recently with functional reactive programming and what it is, and when i was trying to implement something like it in c++, i turned to the lambda for some help. I came up with the beginnings of something like this,
template<class T>
class Reactive
{
public:
Reactive(T data)
{
m_Data = data;
}
Reactive(std::function<T()> func, T data)
{
m_Data = data;
m_Affecter = func;
}
template<class H>
Reactive & operator+(const H & rhs)
{
m_Data += rhs;
return *this;
}
template<class H>
Reactive operator+(Reactive<H> & rhs)
{
std::function<decltype(m_Data + rhs.m_Data)()> func;
if (!rhs.m_Affecter)
func = [&](){return m_Data + rhs.m_Data;};
else
func = [&](){return m_Data + rhs.m_Affecter();};
return Reactive<decltype(m_Data + rhs.m_Data)> (func, m_Data + rhs.m_Data);
}
Reactive & operator=(const T & data)
{
m_Data = data;
return *this;
}
Reactive & operator=(const Reactive & rhs)
{
m_Data = rhs.m_Data;
m_Affecter = rhs.m_Affecter;
return *this;
}
T & Get()
{
return m_Data;
}
void Update()
{
m_Data = m_Affecter();
}
private:
std::function<T()> m_Affecter;
T m_Data;
};
It only support addition thus far. i was trying to make an object called a reactive that can wrap around any other type, except that when a math operation is performed on it, a lambda is created, where that operation takes place, so as to kind of remember what has been done to it before, and to do it again when one of it's affecting values has changed, (after calling the update function). for example if i were to do this.
Reactive<int> cheh = 0;
Reactive<int> meh = 3;
Reactive<int> peh = 7;
cheh = meh + peh;
meh = meh + 4;
cheh.Update();
std::cout << cheh.Get();
then heres what would take place. summing the two Reactives in line five would make another Reactive with their two values added to 10 as well as set it's affector to a lambda that does something like this, &{meh.m_Data + peh.m_Data} . Then that Reactive would be assigned to cheh. When the value m_meh had 4 added to it, and cheh was updated, it's affector was called with the new value of 14 and that is what is printed to the screen, exactly as i'd intended.
But then i got to thinking, what if one of those Reactives that takes part in cheh's affecter goes out of scope. The program should error out, if not handled correctly.
So i did this,
Reactive<int> cheh = 0;
Reactive<int> meh = 3;
{
Reactive<int> peh = 7;
cheh = meh + peh;
peh = peh + 4;
}
cheh.Update();
std::cout << cheh.Get();
At the point when update is called, the Reactive peh that took place in his affecter has gone out of scope and no longer exists. However, this program and cheh's affecter execute successfully and it prints out 14 just as before. I know that the values in the lambda were passed in by the reference capture, so how can the affecter function still access the reference to peh? Does an object or integral type passed into a lambda by reference force them to persist as long as the lambda exists? Something smell's fishy...
I know that the values in the lambda were passed in by the reference capture, so how can the affecter function still access the reference to peh? Does an object or integral type passed into a lambda by reference force them to persist as long as the lambda exists? Something smell's fishy...
The program has Undefined Behavior. Capturing by reference, as you suspect, does not prolong the lifetime of the objects those references are bound to, and dereferencing a reference to an object which no longer exists is UB.
However, Undefined Behavior does not necessarily mean that a crash will occur. It is possible (as seems to be the case here) that the program will just seem to work fine. This might not be true on another machine, or after you reboot your machine.
Also see this brilliant explanation of why it may seem that objects can be accessed even after they have fallen out of scope.
Related
I want to return a boolean or success/failure enum from the function and modify an argument by reference. However, I want to construct a reference in the calling function instead of copying the value.
I have some container (say 'example_q' of type std::queue). queue.front() will return a reference to the value stored in the queue. I can make a copy of that reference (example A) or I can take a reference of that reference (example B), allowing the value to stay in the queue but be utilized outside of it.
A)
int a = example_q.front();
B)
int& b = example_q.front();
Using this difference I could also return the queued value:
A)
int get_front()
{
int a = example_q.front();
return a;
}
B)
int& get_front()
{
return example_q.front();
}
Using option 'B' I can avoid unnecessary copies without moving the data out of the queue via std::move() semantics.
My question is, can I do 'B' via an argument passed by reference? Would I need to use std::move()/rvalues/&& somehow?
void get_front(int& int_ref)
{
// somehow don't copy the value into referenced int_ref, but construct
// a reference in the caller based on an input argument?
int_ref = example_q.front();
}
The problem this would solve is making API match other functions that modify reference arguments but return a success/failure value, ie:
if(q.get_front(referrence_magic_here))
{
...
}
I could reverse the order to get the desired result, IE:
int& get_front(bool& success)
{
...
}
But I'd rather keep the pattern of my API as well as being able to do it via a single line in the if() statement if possible.
Perhaps something like:
bool get_front(int&& int_rvalue)
{
...
int_rvalue = example_q.front();
...
return true_or_false;
}
void calling_func()
{
...
if(get_front(int& magical_ref))
{
... //use magical_ref here?
}
...
}
No, you can't do that.
Other than in its initialiser, a reference behaves like the thing it refers to. By passing it as a function argument, you "hide" the initialiser from the part that wants to do the assignment. So, the function has no access to the referencey behaviour of the thing.
You will have to use pointers if you want to do that:
void get_front(int*& int_ptr)
{
int_ptr = &example_q.front();
}
int* ptr = nullptr;
get_front(ptr);
// optional:
int& ref = *ptr;
(Ew!)
Option B was fine.
This code is invalid C++:
if(get_front(int& magical_ref))
You cannot declare a new variable as you're passing it to a function. And because a reference variable must be declared and initialized at the same time, it wouldn't be possible to have a reference be initialized by passing it to a function.
You could however, do this:
if(int &magical_ref = get_front()) {
But note that you'd be checking whether magical_ref is 0 or not, which is different from the condition you have in your example.
If your logic is as simple as comparing the int, you could do:
if (int& magical_ref = get_front(); magical_ref == 42)
You can return a std::tuple<int&, /* status condition */> and check the status. For example:
std::tuple<int&, bool> get_front() {
static int example = 0;
return {example, false};
}
...
// C++17's structured bindings + if statement with initializer
if (auto [ref, success] = get_front(); success) {
ref = 42;
}
Demo
How can I overload the operators of a class, so that using syntax of
classInstance[index] = value;
performs
classInstance.cfgfile.Write(index,value)
background info; feel free to skip.
The application we develop uses a memory-mapped access to a segment of NVRAM - actually, mapped are just two registers, address and data. You write to the address register, then either write or read the data register. After initialization, the reads and writes are performed by a simple [] overload of the class holding the reference to the segment of memory. You refer to the instance's [] giving a namespaced index of the cell you want to read and write and it does its thing.
int& IndirectMemory::operator[](RTCMemIndex idx)
{
*midx_reg = idx;
return *mdata_reg;
}
(code stripped of irrelevant elements like mutexes and sanity checks).
Everything works fine... as long as the NVRAM works fine. This specific chip is out of production, and the ones 'out in the wild' began dying of old age currently. Their functionality is of low significance to our use, and we could shift their role to the flash memory with nearly no impact (just a little more flash wear) if the chip goes corrupt. Thing is we want to use the flash record using our config format, which uses getters and setters.
int TCfgFile::ReadKey(std::string Key);
void TCfgFile::WriteKey(std::string Key,int data);
And in many places of the code we have calls to NVRAM through IndirectMemory[Some_Register] = Some_Value; writting assorted things that change frequently and we want to persist through reboot. I'd like to retain this syntax and behavior, but be able to write to the file if NVRAM is detected to be corrupted or manually disabled through a config entry.
The net is rife with examples of using operator[] for setting given value just by returning the reference to it. For example:
unsigned long operator [](int i) const {return registers[i];}
unsigned long & operator [](int i) {return registers[i];}
In that case if I call, say, reg[3] = 1; the [] will return a reference to the element#3 and the default operator= will write to the reference just fine.
But since I can't return a reference to a key in the file (.WriteKey() just performs a complete write, returning success or error), and operator= doesn't take an index, I'm afraid this simple option won't help.
You can use a proxy class to solve this. Since value can't be passed into classInstance we need to make an object that operator[] can return that will get the value of value and knows which instance to apply the operation to. Using
struct Proxy
{
classInstance_type& to_apply;
index_type index;
Proxy(classInstance_type& to_apply, index_type index) : to_apply(to_apply), index(index) {}
Proxy& operator=(value_type const & value)
{
to_apply.cfgfile.Write(index,value)
return *this;
}
};
your class's operator[] would look like
Proxy operator[](index_type index)
{
return Proxy{*this, index};
}
and then when you do classInstance[index] = value; you call Proxy's operator= which has a reference to the object to call, the index to use, and the value you also need.
You can also do this without a proxy class. You can make operator[] return a reference to *this and than overload the = operator of said class to perform Write on whatever was given to operator= in the second argument.
#include <iostream>
struct Foo {
void Write(int idx, int value) {
std::cout << "Write(" << idx << ", " << value << ")\n";
}
Foo& operator[](int idx) {
this->index = idx;
return *this;
}
void operator=(int value) {
this->Write(this->index, value);
}
int index;
};
int main() {
Foo f;
f[5] = 10;
}
Prints: Write(5, 10)
I've searched around and can't seem to find an answer to my question. I am doing a project where I have to redefine some operators (+, -, *, etc.) for operations between vectors and polynomials. As far as I know, those operators are supposed to return copies of the objects so as to not modify them directly if we're simply calling the operator (ie vect1+vect2; instead of vect1 += vect2;) and not placing the result anywhere.
Now, I've seen all around that using static variables is a bad practice, but how can I avoid doing that when a method needs to return a copy of the result instead of modifying the object?
The questions here and here didn't really help because they don't address my particular issue.
Here is an example of what I mean:
template <class elem>
Vect_variable<elem>& Vect_variable<elem>::operator+(const Vect_variable& operand)
{
if (taille >= operand.taille)
{
static Vect_variable<elem> temp_v;
temp_v = *this;
for (std::size_t i = 0; i<operand.taille; i++)
{
temp_v[i] += operand.vecteur[i];
}
return temp_v;
}
else
{
static Vect_variable<elem> temp_v;
temp_v = operand;
for(std::size_t i = 0; i<taille; i++)
{
temp_v[i] += vecteur[i];
}
return temp_v;
}
}
In this case you can see that I am creating static Vect_variable for the temporary variable used. Is there any way to do this otherwise?
Yes. Don't make the variable static. That way each call to the function will get its own fresh new variable, and you return that.
Also, it's automatic (on the stack) rather than static, you can declare the variable and initialize it in one go.
... and I hadn't noticed you are returning a reference to the vector. Don't do that. Return it by value.
template <class elem>
Vect_variable<elem> Vect_variable<elem>::operator+(const Vect_variable& operand)
{
if (taille >= operand.taille)
{
Vect_variable<elem> temp_v = *this;
for (std::size_t i = 0; i<operand.taille; i++)
{
temp_v[i] += operand.vecteur[i];
}
return temp_v;
}
else
{
Vect_variable<elem> temp_v = operand;
for(std::size_t i = 0; i<taille; i++)
{
temp_v[i] += vecteur[i];
}
return temp_v;
}
}
The next thing to do, is to notice that you are doing almost the same thing in both branches. It just depends on which taille is shorter. So use a pair of pointers:
{
decltype(this) one, two;
if (taille >= operand.taille)
{
one = this;
two = &operand;
}
else
{
one = &operand;
two = this;
}
Vect_variable<elem> temp_v = *one;
for (std::size_t i = 0; i<two->taille; i++)
{
temp_v[i] += two->vecteur[i];
}
return temp_v;
}
The final comment is that it is usually good practise to write operator += first, and then write operator + as a non-member binary function with signature:
TYPE operator +(TYPE lhs, const TYPE& rhs)
{
lhs += rhs;
return lhs;
}
Note that lhs is taken by value (so you already have your own copy of it). The advantage of the non-member function is that if you have any conversion functions to TYPE, they will operate symmetrically on the left- and right- hand side.
The robust and simple method is to return a (non static) local variable by value. In some cases that is also the efficient method.
If you care a lot about efficiency, then you want an alternate execution path for the cases where one of the two inputs is an rvalue. In that case, you don't want a local variable at all. Instead you want to take an input by rvalue reference, modify it and return it by rvalue reference.
To avoid an excess of duplicate code, you probably want to define an operator+= and put the real work in that method and have all versions of operator+ delegate the work to operator+=
There are situations in which returning a static variable by reference is more efficient than all the above. But there aren't a lot of such situations and they are filled with enough hazards that you shouldn't make that choice.
Having seen the comments you made on the earlier answer: You are correct that returning a static by reference avoids the big problem in having a polymorphic return from an override of a virtual function. But it does so at the expense of creating its own problems. For a trivial example, consider someone using your + to compute A+(B+C). Don't ask why they put in those inappropriate (). Just realize they had no way to know they shouldn't. So your operator copies B to a static and adds C to that, then it copies A to the same static and adds the static to that and returns 2A. While that example is contrived, it is just one of many things you might do with + that go horrible wrong if it returns a reference to a static.
Alright, so I have looked around online and clearly my problem is that I'm using a variable "val" here that stops existing when the function closes. Unfortunately, I haven't really found any actual solutions to my problem here. I'm sure this is an easy enough problem to solve once you know how, but I just don't have the knowledge.
In this code, just notice I'm trying to return an unsigned int val. I can't do that because the code wants a reference, not just a variable. I can't simply return val but I don't know what to do.
http://i.imgur.com/E8sf2aS.png
Thanks for the help.
Edit: sorry, I had some problems with the image, apparently I need to work on my rep.
I'm going to take a wild guess.
Foo& doStuff()
{
// blah blah
Foo val;
// ...
return val;
// val is no longer valid end of scope. Returning invalid reference.
}
Either pass in the result Foo instance to doStuff, or create a new Foo on the heap and return as pointer.
So,
void doStuff(Foo& val)
{
// blah blah
// ...
val = x;
}
or
Foo* doStuff()
{
// blah blah
Foo* val = new Foo; // dont forget to delete
// ...
return val;
}
Of course, you can return by value:
Foo doStuff()
{
// blah blah
Foo val;
// ...
return val;
}
Depending on how heavy a Foo is. Of course, since in this case a Foo is just an small int, you should simply return by value. For some cases of return by value for large/non-trivial types, a temporary copy is created (In those instances where there is no copy elision via RVO or NRVO); in these cases you might want to avoid returning large object types by value.
This code has a lot of problems, apart from being given in an image (!!!)
I guess you're trying to find the element at position pos-1 in a list, or something. The main problem referring to your question seems to be that you're first assigning val by value, then you have no reference to return. You should return n2->value directly, which should be a reference to unsigned int, like that:
const unsigned int &list::operator[](unsigned int pos) const
{
node *n1 = ???, *n2 = ???;
for (unsigned int k = 0; k < _size; k++)
{
if (k == pos)
return n2->value;
n1 = n2->next;
n2 = n1;
}
return ???;
}
Other problems remain, e.g.
why you need two node* and not just one (looking for position pos-1 directly)
how to initialize n1, n2 (somehow pointing to the head of your list; obviously new node() should not work)
what to return if input argument pos is out of range (possibly return a reference to some static variable that you can detect, or throw an exception)
For these problems, more context would be needed from your side.
Reference variables, are only valid if the object to which "refer" to, exists in memory. Passing around references to an out of scope variable, is considered undefined behavior.
This is the mistake in your code.Please correct it.
const unsigned int& list::operator[] (unsigned int pos)const
{
const unsigned int val = 0;
return val; //this is a local variable, whose scope ends here, a reference to this should not be returned
}
This is the compiler's warning, to your code.
warning: reference to local variable ‘val’ returned [enabled by default]
Please listen to compiler warnings (especially c/c++ !!), in your case simply using pass by value, would have been sufficient.
Edit:
In case the return variable, is enforced to be a reference type, and cannot be avoided, you can then extend the life of you local variable, to throughout the existence of the program by making it static.
const unsigned int& list::operator[] (unsigned int pos)const
{
static const unsigned int val = 0;
return val;
}
Th variable val is now a static local variable, whose life is throughout the program,
so pasing around references to this variable should be OK, but not recommended programming,
since a pass by value will suffice for the needs of your application.
I have native C++ class SrcClass containing the following:
std::vector<shotEntry> objectsQueue;
bool getRelatedEntry(const entryToProcess *entriesDeets, int &i) const {
if (i >= (int)objectsQueue.size()) {
i = 0;
return false;}
if (!objectsQueue.size()) return false;
entriesDeets = &(objectsQueue[i++]);
return true;
}
In my client I have:
const entryToProcess *entriesDeets = NULL;
int i = 0;
while (srcObj->getRelatedEntry(entriesDeets, i)) {
When I step through getRelatedEntry the formal parameter, entriesDeets is updated as expected before returning. When it returns the actual parameter of the client is not updated.
This is in some big project I have returned to after two months away. I'm pretty sure the last refactoring I did was to introduce these damnable vectors. It takes ages to compile when I mess with headers. Am I getting confused with the initialize once/ readonly/ const'ness of C#? Can I get away with the client getting a read only native object back?
This is because you are setting the value of the function's parameter. You want:
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
...
*entriesDeets = &(objectsQueue[i++]);
...
and
srcObj->getRelatedEntry(&entriesDeets, i)
entriesDeets is a local variable inside getRelatedEntry. You only modified the local, you didn't affect the value passed in. You need to pass a reference to pointer or a pointer to pointer.
The pointer is updated, but it is the internal copy inside the function. If you want that change to be visible outside of the function, you should pass a reference:
// v
bool getRelatedEntry(const entryToProcess *&entriesDeets, int &i) const {
Or in C style a double pointer and dereference it internally on every usage:
// v
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
// ...
*entriesDeets = &(objectsQueue[i++]);