persistent pointer to vector element in place of 'this'

Multi tool use


persistent pointer to vector element in place of 'this'
I need persistent pointers to elements of std::vector
. Straightforward this
won't do, as demonstrated here:
std::vector
this
#include <functional>
#include <vector>
#include <iostream>
class A {
public:
A() = delete;
A(int i)
: my_i(i)
, whoAmI([this]()->void{ std::cout<<"I am class A with i="<<my_i<<std::endl; })
{}
A(const A&) = delete;
A(A&&) = default;
int my_i;
std::function<void()> whoAmI;
};
int main()
{
std::vector<A> vec;
std::cout << "Initialization:" << std::endl;
for (int i=0; i<3; ++i) {
vec.push_back(A(i));
vec.back().whoAmI();
}
std::cout << "Retrieval:" << std::endl;
for (int i=0; i<3; ++i)
vec.at(i).whoAmI();
}
Which yields
Initialization:
I am class A with i=0
I am class A with i=1
I am class A with i=2
Retrieval:
I am class A with i=2
I am class A with i=2
I am class A with i=2
whereas I need
Retrieval:
I am class A with i=0
I am class A with i=1
I am class A with i=2
Of course, in this example one could easily work around. In real life, the persistent pointer shall be passed to Qt::connect
.
Qt::connect
std::enable_shared_from_this
@FrançoisAndrieux Sounds like a pretty heavyweight solution. But on second thought, maybe the best.
– Passer By
46 mins ago
Surprised this didn't fault, as the capture of
this
and saving it in the std::function
is invalided when the vector has to reallocate.– Richard Critten
41 mins ago
this
std::function
@Richard Critten It does not even fault if the loop limit is set to a million instead of 3.
– Joachim W
37 mins ago
There is really no solution, as vector elements are moved all the time and can even be deallocated when vector expands. The closest thing to a solution is having a vector of pointers. Another possibility is to use
list
.– Arkadiy
35 mins ago
list
2 Answers
2
You are binding this at inizialization site of your lambda, so this is not going to work in in any circumstance the object is moved or copied indeed.
A possible solution could be to add a level of indirection:
#include <functional>
#include <vector>
#include <iostream>
class A;
class fuction_wrapper
{
public:
A* ref;
std::function<void(A*)> lambda;
void operator()() const { lambda(ref); }
};
class A {
public:
A() = delete;
A(int i)
: my_i(i)
, whoAmI({this, (A* a) { std::cout<<"I am class A with i="<< a->my_i << std::endl; }})
{}
A(const A&) = delete;
A(A&& a)
{
my_i = std::move(a.my_i);
whoAmI = { this, std::move(a.whoAmI.lambda) };
}
int my_i;
fuction_wrapper whoAmI;
};
int main()
{
std::vector<A> vec;
std::cout << "Initialization:" << std::endl;
for (int i=0; i<3; ++i) {
vec.push_back(A(i));
vec.back().whoAmI();
}
std::cout << "Retrieval:" << std::endl;
for (int i=0; i<3; ++i)
vec.at(i).whoAmI();
}
Probably not the most eye-candy solution available but it works.
Maybe try capturing indexes by value like this:
#include <functional>
#include <vector>
#include <iostream>
class A {
public:
A() = delete;
A(int i, std::vector<A> &vec)
: whoAmI([i, &vec]()->void{
std::cout<<"I am class A with i="<< i << ". Calling whoAmI(): " << std::endl;
vec[i];
})
{}
A(const A&) = delete;
A(A&&) = default;
std::function<void()> whoAmI;
};
int main()
{
std::vector<A> vec;
std::cout << "Initialization:" << std::endl;
for (int i=0; i<3; ++i) {
vec.push_back(A(i, vec));
vec.back().whoAmI();
}
std::cout << "Retrieval:" << std::endl;
for (int i=0; i<3; ++i)
vec.at(i).whoAmI();
}
Won't help when it comes to
Qt::connect
... except if I access some global variable to access vec
in order to access vec[i]
.– Joachim W
31 mins ago
Qt::connect
vec
vec[i]
@JoachimW You can additionaly store reference/shared_ptr to the vector in the lambda. This will make it usable, right?
– bartop
27 mins ago
Yes, that goes into the right direction
– Joachim W
26 mins ago
@JoachimW Now
A
should work as persistent pointer. Even though I do not know what it is for ;)– bartop
19 mins ago
A
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I'm not sure I understand the problem, but I suspect
std::enable_shared_from_this
may solve it.– François Andrieux
49 mins ago