Returning unique_ptr in Factory
Asked Answered
R

5

11

Maybe this is a simple question, because I'm still new to C++. I would like to use some kind of factory to encapsulate the logging in my application. The idea is that only the factory knews which concrete class will handle the function calls. The application will always call abstract interfaces of the base logging class.

The factory method should look like:

std::unique_ptr<AbstractLoggingClass> Factory::getDefaultLogger(const std::string& param){
    return new ConcreteLoggingClass(param);
}

ConcreteLoggingClass is a subclass of AbstractLoggingClass.

But I get the following error:

Error: could not convert '(operator new(64ul), (<statement>,
((ConcreteLoggingClass*)<anonymous>)))' from 'ConcreteLoggingClass*'
to 'std::unique_ptr<AbstractLoggingClass>'

My problem is that I don't know how to instantiate ConcreteLoggingClass and return a unique_ptr to AbstractLoggingClass

I already found this post, but I still don't see the solution.

Refluent answered 21/12, 2015 at 13:59 Comment(2)
Why? Could you please explain instead of just silently downvote.Refluent
I still don't get the downvote. But thanks to everybody else for the useful answers.Refluent
P
15

The std::unique_ptr constructor you want is explicit, hence you need to be... well... explicit about it. Try

return std::unique_ptr<AbstractLoggingClass>(new ConcreteLoggingClass(param));
Papillon answered 21/12, 2015 at 14:3 Comment(2)
That did the job. Thank you very much!Refluent
Correct answer as far C++ goes, but I don't know why C++ made this decision. A ConcreteLoggingClass is a AbstractLoggingClass using the "is a" in the sense of the Liskov Substitution Principle.Mulciber
D
14

If you can use C++14 you should use std::make_unique:

return std::make_unique<ConcreteLoggingClass>( param );

otherwise explicitly create std::unique_ptr:

return std::unique_ptr<AbstractLoggingClass>{ new ConcreteLoggingClass{param}};
Darryldarryn answered 21/12, 2015 at 14:11 Comment(1)
I dont have C++14 yet. But I already knew about make_unique. This looks very handy.Refluent
C
1

The constructor of std::unique_ptr<T> is explicit. It won't implicitly convert from a pointer as doing so would mean a pointer is silently deleted.

You can return a std::unique_ptr<T> explicitly constructing it, e.g.:

return std::unique_ptr<AbstractLoggingClass>(new ConcreteLoggingClass(param));
Cherub answered 21/12, 2015 at 14:4 Comment(0)
P
1

You can't convert your pointer to a unique_ptr, you have to create it :

std::unique_ptr<AbstractLoggingClass> Factory::getDefaultLogger(const std::string& param){
    return std::unique_ptr<AbstractLoggingClass>(new ConcreteLoggingClass(param));
}
Primula answered 21/12, 2015 at 14:5 Comment(0)
B
1

if you have c++14 or better:

std::unique_ptr<AbstractLoggingClass> 
Factory::getDefaultLogger(const std::string& param)
{
    return std::make_unique<ConcreteLoggingClass>(param);
}
Bjorn answered 21/12, 2015 at 14:10 Comment(1)
I have no c++14 available at the moment. But thank you for making this suggestion, maybe I can use this in the future.Refluent

© 2022 - 2024 — McMap. All rights reserved.