3

I have a container which I'd like to fill with pointers to class C. However, I'd rather use Boost shared_ptr than dumb pointers.

I declare the container as container<C*>, but then get this error:

 no known conversion for argument 1 from ‘boost::shared_ptr<C>’ to ‘C* const&’ 

How should I declare the container to take boost shared ptrs? If possible, I'd like it to take dumb pointers as well.


UPDATE: From the responses, it seems that the container must indeed be declared to take smart pointers, it can't be made to take both smart or dumb pointers. That is, there's no coercion from smart to dumb or versa. Is that correct?

7
  • You might actually want a Boost ptr container. Commented May 27, 2015 at 0:05
  • container<boost::shared_ptr<C>> ... is that what you're looking for? If not, can you show some code of what you're trying to do. Commented May 27, 2015 at 0:06
  • Please create a MCVE, error messages without the code that causes them are notoriously useless. Commented May 27, 2015 at 0:06
  • Seems like a repeat. Did you google this before posting ? stackoverflow.com/questions/4577838/… Commented May 27, 2015 at 0:31
  • 1
    So, a shared ptr and a non-shared ptr have very different behavior on construction, copying and destruction. What, exactly, do you want your container to do with this mixture of smart and dumb pointers? When you access element #17 (say), what type do you want to access? What should happen when your container is copied? What code determines the lifetime of the resources pointed to by the dumb pointers? Do you have a business case for a mixture of smart and dumb pointers? Why shared ptr for your smart pointer? These are not rhetorical questions. Commented May 27, 2015 at 0:54

2 Answers 2

5

Here is a simple working demo using C++11 shared pointers. They are analogous to Boost shared pointers.

#include <iostream> #include <memory> #include <vector> int main( int argc, char* argv[] ) { // Create vector std::vector<std::shared_ptr<int>> buffer; for( int i=0; i<10; i++ ) buffer.push_back(std::make_shared<int>(i)); for( int i=0; i<10; i++ ) if( (*buffer[i]) != i ){ std::cout << "Match invalid for " << i << "." << std::endl; return 1; } std::cout << "Valid result" << std::endl; return 0; } 

I compiled this using

g++ main.cpp -o main -std=c++11 
Sign up to request clarification or add additional context in comments.

3 Comments

In what way does this demonstrate a vector containing both smart and dumb pointers?
You can query the std::shared_ptr for the internal dumb pointer using std::shared_ptr<T>::get. Otherwise, you can create a class with both a shared_ptr and normal pointer to allow you to check for either. That is a pretty ugly solution though.
Yes, but the OP asked for a way to store dumb pointers in the container. Storing a dumb pointer in a smart pointer is doable (even without making it behave smart in the case of std::shared_ptr<T>!), but the above doesn't demonstrate it happening.
2

In order to use vectors you need to explicitly specify the type of objects that they will be holding.In your case it will be boost::shared_ptr. I also understand that you want to store dumb pointers in that container. You probably mean raw pointers.As mentioned earlier your container can primarily store one type however there are exceptions for instance the types are related via inheritance or another mechanism (such as serialization) for which some explicit down-casting would be required when you attempt to use those objects or the type is a generic type. Never the less. Here is another approach. You don't need a vector that stores both a smart pointer and a raw pointer since you could always obtain a raw/dumb pointer from a smart pointer. Your best approach is to create a vector like this

std::vector<boost::shared_ptr<foo>> vec; 

The above creates a vector that will store shared pointers to foo.

Then when ever you have a shared pointer as such

 boost::shared_ptr<foo> foo_ptr(new foo()); 

You can do something like this

vec.push_back(foo_ptr) 

When you need the dumb pointer you could do this

foo* f = vec[0].get(); 

I read your update in which you stated

... it seems that the container must indeed be declared to take smart pointers, it can't be made to take either smart or dumb pointers.

You should understand that boost::shared_ptr<Type> is a smart pointer.

4 Comments

No: what the OP asks is possible. I can write it more than one way. The question is, what way does the OP want it done, not "this is not possible".
From what I understand is that OP wants to contain both types in a std::vector. I am not sure how a std::vector can contain multiple types if they are not related.
Lots of ways: union, std::aligned_storage, void*&type_id* at a lower level, std::experimental::any, boost::variant, custom type erasure at a higher level? My issue is that you said "you cannot do this". Maybe they should not do it. Probably you don't know how to do it. But be careful in C++ when you say "this cannot be done": knowing what cannot be done sometimes requires knowing everything that can be done!
The OP asked to store dumb pointers in the container. Amusingly, by putting a noop deleter into a std::shared_ptr, you can make it store a dumb pointer. Not sure if that is a good idea.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.