0

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.

Using Ron's advice in this post and this so post I came to the following code:

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

class A
{
public:
    A()
    {
        m_numbers = { { 3, 1 ,4, 1, 5} };
    }

    void display()
    {
        auto cleanNumber = [](decltype(m_numbers)* numbers){ 
            if(numbers) 
                move(*numbers);
        };
        auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&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;
}

This gives the following errors: (sorry for the formatting)

g++ -std=c++17 -o main2 main2.cpp                                   
In file included from d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\memory:81:0, from main2.cpp:3:
d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\bits\unique_ptr.h: 
In instantiation of 'std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) 
[with _Tp = std::vector<int>; _Dp = A::display()::<lambda(std::vector<int>*)>; std::unique_ptr<_Tp, _Dp>::pointer = std::vector<int>*]':
main2.cpp:20:87:   required from here 
d:\program files\minggw\lib\gcc\mingw32\5.3.0\include\c++\bits\unique_ptr.h:170:33: 
error: use of deleted function 'A::display()::<lambda(std::vector<int>*)>::<lambda>()'
: _M_t(__p, deleter_type()) 
 main2.cpp:16:23: note: a lambda closure type has a deleted default constructor
 auto cleanNumber = [](decltype(m_numbers)* numbers){

I think I understand that I cannot pass a decltype of this lambda since the default constructor is deleted. How do I pass the correct lambda deleter then?

Looking around so I came to this answer that seems equivalent but I do not understand why that would work and what makes my code different?

n.b. I am not sure if I should've edited my original question. I think this is not a clarification but asking for further advice so I made a new question, hope that's in accordance to the rules.

turoni
  • 1,345
  • 1
  • 18
  • 37
  • Several things: It looks like you want to implement a [scope guard](https://stackoverflow.com/questions/31365013/what-is-scopeguard-in-c), you don't really need to use a unique_ptr for this! Second, just calling move(*numbers) does nothing, you need to assign this value to some local variable that gets deleted later. Third, you need to explicitly specify your deleter in your unique_ptr, like VTT mentioned already – Tobias Ribizel Jul 18 '17 at 10:35
  • @TobiasRibizel I am reading up on scope guard now, I think that is probably the answer to [this question](https://stackoverflow.com/q/45162233/3681671) – turoni Jul 18 '17 at 10:47
  • @TobiasRibizel I read the scope guard link and while it does seem like what I want I do not see how this would be better unless there is some std implemented scope guard. – turoni Jul 18 '17 at 10:56
  • As far as I know, there is no general implementation in the std library, but using a `unique_ptr` for this is a rather ugly way of solving the original problem. If the need for such a scope guard comes up more often, adding a simple 10 line implementation wouldn't hurt ;) – Tobias Ribizel Jul 18 '17 at 10:59
  • Beauty is in the eye of the beholder, I find the extra class uglier than this. Yet if I need to use it in different places I will probably add a separate class for it, as I originally was doing before being pointed to this solution. – turoni Jul 18 '17 at 11:09

1 Answers1

1

You need to pass cleanNumber into unique_ptr constructor:

auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&m_numbers, cleanNumber);

Also your lambda does not clear vector content as move(*numbers); does nothing. You should write numbers->clear(); instead.

user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Thanks that's it. Clear is indeed a better here. I still used move as a bit of a refactoring artifact but that's unnecessary now. – turoni Jul 18 '17 at 10:44