0

Reference Well, how does the custom deleter of std::unique_ptr work?

Constructor

std::unique_ptr<ErrorHandling> error_;

RecursiveDescentParser::RecursiveDescentParser(std::string inputStream, bool fileService, 
            boost::optional<std::string> filePathName, std::ofstream &writer){

    if (fileService == true){
        error_(new ErrorHandling(fileService, writer));  <---- compiler error
    }
    else{
        error_(new ErrorHandling(fileService, std::ofstream())); <---- compiler error
    }       
}

Compiler error

Error   1   error C2247: 'std::default_delete<_Ty>::operator ()' not accessible because 'std::unique_ptr<_Ty>' uses 'private' to inherit from 'std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>'

Cause of error described here.

I decided since 'std::default_delete<_Ty>::operator () is private because child class (std::unique_ptr in this case) has specified private inheritance that I would write my own custom deleter. Problem is I am too uncomfortable with the syntax and notation to succeed.

Community
  • 1
  • 1
Mushy
  • 2,535
  • 10
  • 33
  • 54

2 Answers2

5

This line

error_(new ErrorHandling(fileService, writer));

is an error because unique_ptr doesn't have an operator(). The error message is a bit misleading, because its base class seems to have one (but luckily private).

You probably intended

error_.reset(new ErrorHandling(fileService, writer));

which makes the unique_ptr own a new object.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Even if there is no initial object, it is safe to call reset to initialize a std::unique_ptr? – Mushy Apr 08 '13 at 17:15
  • Yes, the default constructor you used will set the initial pointer to null. It's quite ok to replace that with a real pointer. – Bo Persson Apr 08 '13 at 17:18
4

The problem is that you're trying to use the function-call operator on a unique_ptr, which is not a valid thing to do. Then some confusion is caused because your particular implementation happens to have an inaccessible operator, rather than no operator at all, giving a weird error message.

I assume you're actually trying to reset error_ to own a new pointer:

error_.reset(new ErrorHandling(fileService, writer));
//    ^^^^^^

UPDATE: if you do want a custom deleter (which, to reiterate, you don't in this situation), it might look like:

struct ErrorHandlingDeleter
{
    void operator()(ErrorHandling * p) {/* do something to release the pointer */}
};

std::unique_ptr<ErrorHandling, ErrorHandlingDeleter> error;
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • I was trying the following syntax `std::unique_ptr error_(new ErrorHandling(fileService, writer));` but received the compilation error proceeding what I thought was a need to define my own custom deleter. Even though utilizing `reset` is the solution, can I please see a SSCCE custom deleter example? – Mushy Apr 08 '13 at 17:18
  • @Mushy: That's the syntax to declare and initialise a new unique pointer. However, you don't want to do that; you want to modify an existing one, and for that you need to call `reset`. `error_(some_pointer)` does something completely different - it tries to call the unique pointer like a function, which is impossible. – Mike Seymour Apr 08 '13 at 17:21
  • @Mushy: For an example of custom deleters, Google pointed me to http://stackoverflow.com/questions/8274451 and many other places. But of course, you don't want a custom deleter here; they are only for when `delete` isn't the right thing to do. – Mike Seymour Apr 08 '13 at 17:23
  • That link I have referenced at the top of my question. The syntax of that link was not very clear to me and thus I decided to ask for a clearer example. Not even my textbook provides a very clear example. – Mushy Apr 08 '13 at 18:08
  • @Mushy: OK, I've added an example of a custom deleter. I've no idea whether that's clearer than your textbook, though. – Mike Seymour Apr 08 '13 at 18:40