Reputation: 1435
I have some function where I need to use a member variable(a vector of custom classes).
At the end of this function this member needs to be cleared but it needs to stay as a member for the duration of this function.
Another problem is that the function can end prematurely due to custom error handling of the program. Yet the member still needs to be cleared.
I first moved this member at the beginning in a local variable using std::move. This worked pretty well but it now turns out I need the variable to stay as a member variable till the end of that function.
I came up with the following solution using a unique_ptr with a reference that will do the move upon destruction.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
template <class T>
class Clean
{
public:
Clean(T& clean)
: m_clean(clean) {}
~Clean()
{
T destroy = move(m_clean);
}
private:
T& m_clean;
};
class A
{
public:
A()
{
m_numbers = { { 3, 1 ,4, 1, 5} };
}
void display()
{
auto cleanNumbers = make_unique<Clean<vector<int> > >(m_numbers);
for(int number: m_numbers)
cout << number << endl;
}
private:
vector<int> m_numbers;
};
int main()
{
A a;
a.display();
cout << "should be empty now" << endl;
a.display();
return 0;
}
Any cleaner solutions are also welcome but my actual question is the following.
Is there any std equivalent of the Clean class I used?
Ps: code fragment compiles for me using g++ 5.3.0
g++ -std=c++14 -o main main.cpp
Upvotes: 1
Views: 423
Reputation: 6471
You could use a shared_ptr's custom deleter to obtain the same result.
void A::display()
{
std::shared_ptr<int> dummy (
(int*)alloca(sizeof(int)), // very fast allocate on stack
[&](int*) { this->m_numbers.clear(); }
);
for(int number: m_numbers)
cout << number << endl;
}
Here is the entire code, compiles fine, gcc 5.3 -Wall -Wpedantic -march=native -std=c++14
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class A
{
public:
A()
{
m_numbers = { { 3, 1 ,4, 1, 5} };
}
void display()
{
std::shared_ptr<int> dummy (
(int*)alloca(sizeof(int)),
[&](int*) { this->m_numbers.clear(); }
);
for(int number: m_numbers)
cout << number << endl;
}
private:
vector<int> m_numbers;
};
int main()
{
A a;
a.display();
cout << "should be empty now" << endl;
a.display();
return 0;
}
Upvotes: 1
Reputation: 1435
This is the result I came to thanks to comments and other questions:
void display()
{
auto cleanNumber = [](decltype(m_numbers)* numbers){
if(numbers)
numbers->clear();
};
auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&m_numbers, cleanNumber);
for(int number: m_numbers)
cout << number << endl;
}
Upvotes: 1