I'm trying to learn the kinds of factory patterns I can use in C++. I'm not sure why I can't return a unique ptr. I can return a shared ptr just fine. Here's my code:
class FactoryMethodExample {
FactoryMethodExample() {}
public:
static FactoryMethodExample get_instance() {
return {};
}
static FactoryMethodExample * get_pointer() {
return new FactoryMethodExample;
}
static unique_ptr<FactoryMethodExample> get_unique_instance() {
return make_unique<FactoryMethodExample>();
}
static shared_ptr<FactoryMethodExample> get_shared_instance() {
return shared_ptr<FactoryMethodExample>();
}
void verify() {
cout << "I exist" << endl;
}
};
This code doesn't compile. I get this error :
error: calling a private constructor of class 'FactoryMethodExample'
return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...));
Firstly, your shared_ptr and unique_ptr examples are not comparable.
make_unique creates a unique_ptr initialised with a value.
shared_ptr is just a constructor call of the shared_ptr class, which will leave it initialised with a null pointer.
This is why you are getting two different results.
The reason you have an error, is because you have a private constructor. The easiest solution is to make make_unique (and make_shared) friends.
See the following question for a bit of guidance: How to make std::make_unique a friend of my class
In addition, your function names may be misleading. get_shared_instance implies that the same instance will be returned every time, where I think you want to return a shared_ptr of a new instance?
Related
I came across a weird problem. I get an error message in setGetDog() method when written this way:
class Dog
{
public:
void bark() { std::cout << "Bark!" << std::endl; }
};
class test
{
public:
std::unique_ptr<Dog> setGetDog()
{
if (!dog_)
{
dog_ = std::make_unique<Dog>();
}
return dog_;
}
private:
std::unique_ptr<Dog> dog_;
};
int main()
{
auto testClass = std::make_unique<test>();
auto dog = testClass->setGetDog();
}
Error is like this:
error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Dog; _Dp = std::default_delete<Dog>]'
But when I change the implementation to:
std::unique_ptr<Dog> setGetDog()
{
return std::make_unique<Dog>();
}
It works just fine.
What is the matter with dog_?
I do not understand why the error states that it is deleted when in fact test is still alive when the method was called (and so dog_ as well).
I know I can write this some other way but I'm specifically curious on why behavior is like this on this implementation.
Can anyone please enlighten me?
There are a few different types of value categories/situations that objects have that affects how there are returned from a function. Lets look at the rvalue category first. When you do
std::unique_ptr<Dog> setGetDog()
{
return std::make_unique<Dog>();
}
std::make_unique<Dog>() returns by value making the return object an rvalue. That means that when the compiler returns the object it will implicitly move it. (the compiler can also elide the copy but that doesn't matter for this discussion) Since the object is moved you don't have any issues since std::unique_ptr is movable.
The second case is when you have an lvalue, but it is a function local object. If you had
std::unique_ptr<Dog> setGetDog()
{
auto ptr = std::make_unique<Dog>();
return ptr;
}
Here ptr is an lvalue but it is going away so we can call it an xvalue(expiring value). With xvalues, when you return them the compiler tries to move it, since moving it is a safe operation in this case. If the move operation does not exist/is not viable, then the compiler falls back to copying. Since std::unique_ptr is movable, it gets moved without error.
The last case is when you have a plain lvalue like you have with
class test
{
public:
std::unique_ptr<Dog> setGetDog()
{
if (!dog_)
{
dog_ = std::make_unique<Dog>();
}
return dog_;
}
private:
std::unique_ptr<Dog> dog_;
};
Here, dog_ is a member of the class, not a object local to the function. This means the only thing the compiler can do is try and make a copy. Since you can't copy a unique_ptr, you get an error. You would need return std::move(dog_); for it to compile, but if you did that dog_ in the class would be empty.
When you just return the unique_ptr then return value optimization can be applied. This is because the unique_ptr can actually be constructed at the address of the unique_ptr instance in the calling function. The compiler allows this as no copying is occurring.
When you add the if, the function may or may not be trying to return an existing instance. It's a runtime decision. An existing instance wont have the opportunity to be constructed where the calling function wants it and so must be copied.
unique_ptr has a deleted copy constructor to preserve the unique part of its contract, so the code does not compile.
Depending on your needs you may want to use a shared_ptr, use std::move (mistake probably, it empties the unique_ptr inside your class) or use value semantics to copy the actual object and not the pointer to it.
I am in the process of making a simulation and it requires the creation of multiple, rather similar models. My idea is to have a class called Model and use static factory methods to construct a model. For example; Model::createTriangle or Model::createFromFile. I took this idea from previous java code and was looking for ways to implement this in C++.
Here is what I came up with so far:
#include <iostream>
class Object {
int id;
public:
void print() { std::cout << id << std::endl; }
static Object &createWithID(int id) {
Object *obj = new Object();
obj->id = id;
return *obj;
}
};
int main() {
Object obj = Object::createWithID(3);
obj.print();
return 0;
}
Some questions about this:
Is this an accepted and clean way of making objects?
Does the returned reference always ensure correct removal of the object?
Is there any way to do this without pointers?
Just for the record, here's how this program might look like in proper C++:
class Object
{
int id;
// private constructor, not for general use
explicit Object(int i) : id(i) { }
public:
static Object createWithID(int id)
{
return Object(id);
}
};
int main()
{
Object obj1 = Object::createWithID(1);
auto obj2 = Object::createWithID(2); // DRY
// return 0 is implied
}
This is probably not what people would generally call a "factory", since factories typically involve some dynamic type selection. The term "named constructor" is sometimes used, though, to refer to the static member function that returns an instance of the class.
Your code currently contains a memory leak: any object created using new, must be cleaned up using delete. The createWithID method should preferably not use new at all and look something like this:
static Object createWithID(int id)
{
Object obj;
obj.id = id;
return obj;
}
This appears to require an additional copy of the object, but in reality return value optimization will typically cause this copy to be optimized away.
Is this an accepted and clean way of making objects?
It is (unfortunately) accepted but it's not clean.
Instead of factory functions just use constructors.
That's what they're for.
Does the returned reference always ensure correct removal of the object?
The reference is irrelevant except to the extent that it misleads users of the function.
In your example the reference has apparently misled yourself into not destroying the dynamically allocated object, but just copying it.
Better return a smart pointer.
But as already mentioned, it's even better to ditch the idea of factory functions.
They're wholly unnecessary here.
Is there any way to do this without pointers?
No, not if "this" refers to the dynamic allocation, but you can and should use constructors instead of factory functions.
Example:
#include <iostream>
namespace better {
using std::ostream;
class Object
{
public:
auto id() const -> int { return id_; }
explicit Object( int const id): id_( id ) {}
private:
int id_;
};
auto operator<<( ostream& stream, Object const& o )
-> ostream&
{ return (stream << o.id()); }
} // namespace better
auto main()
-> int
{
using namespace std;
cout << better::Object( 3 ) << endl;
}
By calling Object *obj = new Object(); you do allocate memory on the heap. In the lines following that statement you do return the reference to that object. So far, so good, but you do never delete the object you created to actually free the memory. By calling the function several times you will run in a memory leak.
There are two possible workarounds:
static Object createWithID(int id); would return a copy of the Object you create, so it would be enough to allocate it on the stack using
Object tmp;
tmp.id = id;
use c++11 smart pointer to let them handle the memory.
#include <memory>
static std::unique_ptr<Object> createWithID(int id)
{
std::unique_ptr<Object> tmp(new Object());
tmp->id = id;
return std::move(tmp);
}
This is an absolutely terrible way to create your objects. Every time that createWithID is called, a new Object is constructed on the free store which is never able to be destroyed.
You should rewrite createWithID to:
static Object createWithID(int id) {
Object obj;
obj.id = id;
return obj;
}
Or better, you could just supply a constructor for your Object objects.
If you want to enable polymorphic objects, you should use something like wheels::value_ptr.
Unless you are using polymorphism there is no reason for your factory functions to return any kind of pointer, they can just return the object by value. Any modern compiler will do return value optimization so there is no copy.
If you are after an "accepted and clean" way then that sounds quite opinion based and dependent on how this class will be used but what I would do is keep the definition of Model as small as possible. Only include what is needed for it to do its job with a minimum number of constructors required for normal usage:
namespace Simulation {
class Model {
private:
int id_;
public:
explicit Model(int id) : id_(id) {}
// minimum required to do the job...
};
}
Then, I would define the functions to create various flavors of Model separately. For example, as non-member, non-friend functions in a namespace:
namespace Simulation {
Model createTriangle(int id) {
Model model(id);
// do whatever you need to do to make it a triangle...
return model;
}
Model createSquare(int id) {
Model model(id);
// do whatever you need to do to make it a square...
return model;
}
}
That way, if you find you need another flavor of Model, you don't need to change the Model class. Your create functions can even be spread across multiple files if needed or become part of a Builder or Factory class. Usage would look like:
int main() {
Simulation::Model m1(0);
Simulation::Model m2 = Simulation::createTriangle(1);
Simulation::Model m3 = Simulation::createSquare(2);
}
I'm using a library which returns a reference to me.
I need to use this reference as class-attribute.
Not being able to initialize the attribute in constructor directly (the lib needs to be inited before), I thought about using a shared_ptr for lazy initialization:
#include <iostream>
#include <string>
#include <tr1/memory>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo() :
testString_( std::tr1::shared_ptr< std::string& >() )
{
//do some initialization of the library here...
//now init the shared_ptr
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
std::tr1::shared_ptr< std::string& > testString_;
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
But unfortunately this does not work. g++ gives messages like this:
error: forming pointer to reference type ‘std::string&’
I tried some other ways to get the reference into the shared_ptr, but nothing works... Perhaps you could give me a hint.
Note:
- In "real-world" instead of std::string the datatype is a class without default constructor.
- For those who still wonder: The above is just a simplified example-code :)
UPDATE:
- While trying to apply the suggestions, I found out that contrary to the used std::string from example, my class has a private copy constructor. This means I'm not able to just copy the object into a new one.
If you are provided by a reference only, that means that you are not responsible for memory management, and that in turns means that you cannot use your own memory management. That is, you should not use any type of smart pointer to hold that object.
While you can obtain the address of the real object with the & operator, doing so will cause undefined behavior later on when your shared_ptr goes out of scope and tries to free the memory and the library itself tries to free the memory on it's own.
You simply cannot take the address of a reference.
You can however use shared_ptr<string> and initialize it with &getStringReference. But that will cause the shared_ptr to try to delete the string, causing it to fail since it was never allocated using new. To fix this, make a copy:
testString_.reset(new std::string(getStringReference()))
Even better, let your class just store the reference directly. The you don't need to bother about memory management at all:
class Foo
{
std::string& _testString;
// ...
}
You need to understand the semantics of references and of memory management.
What you probably want is a raw pointer in your class. I assume you can't use a reference because you do not know what object it will refer to until you make the function call so you want to do something like ref=getRef();
You have no way of automatically "protecting" your pointer against becoming "dangling", but do not think there is anything you can do to rectify this situation. You just have to look at the documentation as to how to use the reference/pointer properly.
You could consider using Boost.Optional, which support optional references. This way, you could lazy initialize your reference without taking ownership of the referenced object as you do by using shared_ptr:
#include <iostream>
#include <string>
#include <boost/optional.hpp>
//This is library, cannot touch
std::string globalString = "TEST";
std::string& getStringReference()
{
return globalString;
}
//this is my class which uses the library
class Foo
{
public:
Foo()
{
//do some initialization of the library here...
//now init the optional reference
testString_.reset( getStringReference() );
}
std::string getString() const
{
return *testString_;
}
private:
boost::optional< std::string& > testString_; //<-- note the use of optional
};
//and a main to be compilable and check if the above works...
int main()
{
Foo foo;
std::cout << foo.getString() << std::endl;
}
Stop using shared_ptr now. Sharing is not an unilateral decision.
That being said, you are returned a reference to an object, not the object proper. There are two things you can do:
copy the object, and therefore deciding to manage the lifetime of the copy yourself
take a reference to the object, and let it up to the library you called to manage the lifetime, in which case you'll need to have some knowledge about it
I would definitely recommend copying unless there is a reason not to, much easier to get it right.
If you go for copying, use boost::optional<LibObject> within your class, this way you'll bypass the initialization issue.
If you wish to use a reference, you can still use boost::optional, and it'll work too! Use it as such: boost::optional<LibObject&>, but make sure the object you have a reference to will live long enough.
Finally, regarding the initialization issue, you could use a function to process the initialization and return a reference directly, thus initializing the reference of your class in the initialization list.
You can not use a shared_ptr with a reference type, because a reference is just that - a reference to an object. It is not a real object.
Next example is just simplified version of what you tried to do :
int main()
{
int &* a;
}
Use a factory function?
class Library
{
public:
static void Init();
static LibraryThing & getThing();
};
class Foo
{
public:
static shared_ptr<Foo> Create()
{
if (!_libInit)
{
Library::Init();
_libInit = true;
}
return make_shared(new Foo(Library::getThing()));
}
private:
Foo(LibraryThing & ref) : _ref(ref)
{
}
private:
LibraryThing & _ref;
static bool _libInit;
};
I wrote a class to contain my objects in it.
The code is:
class objectPool
{
private:
struct itemType_{uint count; void* object;};
std::multimap< std::string, itemType_ > pool_;
public:
template<class T>
bool addItem(std::string key, T*& object)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
object = (T*)(*i).second.object;
(*i).second.count++;
return true;
}
i = pool_.insert(std::pair<std::string,itemType_>(key, (itemType_){1, NULL}));
object = (T*)(*i).second.object;
return false;
}
template<class T>
bool removeItem(std::string key)
{
std::multimap< std::string, itemType_ >::iterator
i = pool_.find(key);
if(i != pool_.end())
{
if((*i).second.count == 1)
{
//important to call the appropriate destructor
delete ((T*)(*i).second.object);
pool_.erase(i);
}
else
(*i).second.count--;
return true;
}
return false;
}
};
And the test code:
#include "objectPool.h"
class testClass
{
public:
~testClass()
{
// I should get here at least once
std::cout << "I am deleted teehee";
}
};
testClass* test;
objectPool myPool;
int main () {
if(!myPool.addItem<testClass>("baba", test))
{
test = new testClass;
}
myPool.removeItem<testClass>("baba");
}
For some reason my test object's destructor does not want to be invoked.
First questcha: Why? Where I am wrong?
The sec.: Should I use auto_ptr instead? (Although I want to avoid using templates...)
The third.: Is there a better(-looking) solution? (with or without using templates)
The fourth.: Is there a way to invoke constructor via void pointer without templates (or without knowing the original type)?
Thanks ahead! :D
And sorry for my terrific english (not my native language, although...)
You correctly store a NULL into your T* reference, but that is a reference to the local variable. When you later update that local by calling new, that has no effect on the item stored in the pool.
The easier way to fix this would be to just create the object inside the addItem function using new T.
As for your other question, a way to call the destructor without knowing the original type, there is no way to do that. But there is a trick you can use with templates. You can create a template function like the one below, and then pass around a function pointer to it.
template<typename T>
void deleter(void *ptr)
{
delete static_cast<T*>(ptr);
}
deleter as a simple type which you can typedef and pass around pointers:
typedef void (*deleter_func)(void *);
To get a pointer to it, just do something like this in your addItem function:
deleter_func myDeleter = &deleter<T>;
Then later:
myDeleter(somePtr);
You don't need to know the type of somePtr at the time of deletion, just need to keep a pointer to the deleter. You can also use this method with shared_ptr, which can use a deleter argument.
My guess is it's going wrong because you're inserting {1, NULL} into the map. Changing the value of test in the main function doesn't affect the content of the map.
For some reason my test object's destructor does not want to be invoked. First questcha: Why? Where I am wrong?
Your test code is wrong. You add some uninitialized pointer into the structure. Try this:
int main () {
test = new testClass();
if(!myPool.addItem<testClass>("baba", test))
{
// Duplicate, I presume...
}
myPool.removeItem<testClass>("baba");
}
The sec.: Should I use auto_ptr instead?
std::auto_ptr is designed for dynamically allocated local variables, it is not designed for container implementation. Your current design limits that, anyways. However, I would write the test code as
int main () {
std::auto_ptr<testClass> test(new testClass());
if(myPool.addItem<testClass>("baba", test.get()))
{
test.release();
}
myPool.removeItem<testClass>("baba");
}
The third.: Is there a better(-looking) solution?
Yes, there is some type-safe heterogenous container in boost. I would look at that.
The fourth.: Is there a way to invoke constructor via void pointer without templates (or without knowing the original type)?
You can use the placement new operator if you want to construct an object in pre-allocated memory. std::vector does this a lot. However, there is no way to construct an object without knowing the type. How would you specify what type's constructor to invoke? If you need this, you'll probably want to look into the factory method pattern.
I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};