5

I'm designing a Factory that creates different types of Foo and I'm trying to use smart pointers.

Most seems to be working well, but I am missing some important features (namely nullptr) because of compiler limitations.

I have this method:

std::unique_ptr<Foo> createFoo(const std::string &fooType) {
    auto it = _registeredFoo.find(fooType); // _registeredFoo is a map
    if(it != _registeredFoo.end())
       return std::unique_ptr<Foo>(it->second());
    return std::unique_ptr<Foo>(NULL);
}

When I test this method, it never returns a NULL-like pointer.

This is how I test my method.

std::unique_ptr<Foo> _foo = FooFactory::getInstance()->createFoo("FOO"); //FOO is registered
if(_foo) {
  std::cout << "Hello, World!" << std::endl;
} else {
  std::cout << "Goodbye, World!" << std::endl;
}

std::unique_ptr<Foo> _bar = FooFactory::getInstance()->createFoo("BAR"); // BAR is unregisered
if(_bar) {
  std::cout << "Hello, World!" << std::endl;
} else {
  std::cout << "Goodbye, World!" << std::endl;
}

I always see "Hello, World!"

This leads me to believe that my use of std::unique_ptr's constructor is a bit abusive. Can anyone give me a recommendation for how to approach this without emulating nullptr myself?

I'm using gcc 4.4.6.

13
  • 2
    Won't simply using unique_ptr(); help? Commented Aug 25, 2015 at 12:56
  • 5
    It's actually the same as the default constructor. How did you check that your code "never returns a NULL-like pointer"? Commented Aug 25, 2015 at 12:58
  • 6
    "When I test this method, it never returns a NULL-like pointer." This is the only part of your question that is the real question, yet it lacks detail. Can you explain your problem better? Commented Aug 25, 2015 at 12:59
  • 9
    GCC 4.4.6 is old. When it says "C++0x support is experimental," it really means it. Upgrade if it's at all possible. You're living on the edge. Commented Aug 25, 2015 at 13:11
  • 4
    Uh, you are aware that your code will likely lead to double-frees and/or leaked memory, especially if you get unique_ptr to work as it should? You pass ownership of the pointed to memory from the registry to the unique_ptr you return. The unique_ptr will call delete, and your registry will probably call delete. Same problem if you call createFoo with the same argument twice. Commented Aug 25, 2015 at 13:19

3 Answers 3

7

I think that what you want is an empty unique_ptr:

return std::unique_ptr<Foo>();

It seems that you are looking for a pointer that points to no object (and is false when converted to bool).

Sign up to request clarification or add additional context in comments.

4 Comments

There's nothing wrong with attempting to delete an object at "the NULL address". Frankly I don't see why the OP's code shouldn't work.
A NULLed shared_ptr is valid, but it's hardly idiomatic.
When I convert std::unique_ptr<Foo>(NULL) to bool I do get false.
I really think that this, while a valid suggestion, is not a fix for the OP's problem (whatever that may be).
7

You can use the default constructor of std::unique_ptr.

std::unique_ptr<int> a1();
std::unique_ptr<int> a2(nullptr);

a1 and a2 are unique pointers initialised empty (owns nothing).

you can verify the emptiness of the pointers with the operator bool provided by the unique_ptr class:

if (!a1) { // the smart pointer is empty
}

Comments

6

What you want is

return {};

the {} return a default constructed object of whatever (class) type1, and can be read "nothing". It works with smart pointers, optional, and most everything.

If your compiler lacks this

return std::unique_ptr<Foo>();

will do it. Passing NULL to std::unique_ptr is not legal in C++11 anyhow (the constructor is ambiguous).

You don't have a C++11 compiler. Any use of C++11 in your code is going to be error-prone.


1 The proper wording is complicated. For a scalar (like int), this zero-initializes the value (which, in practice, sets the value to 0/null/0.0/'\0' etc).

2 Comments

What was your 1 footnote going to be?
@Barry An attempt to detangle the initialization word spaghetti that C++11 left us with. I have now included a brief attempt.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.