2

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?

SRobertJames
  • 8,210
  • 14
  • 60
  • 107
  • You might actually want a Boost ptr container. – chris May 27 '15 at 00:05
  • `container>` ... is that what you're looking for? If not, can you show some code of what you're trying to do. – Praetorian May 27 '15 at 00:06
  • Please create a [MCVE](http://stackoverflow.com/help/mcve), error messages without the code that causes them are notoriously useless. – danielschemmel May 27 '15 at 00:06
  • Seems like a repeat. Did you google this before posting ? http://stackoverflow.com/questions/4577838/smart-pointers-in-container-like-stdvector – Rajeshwar May 27 '15 at 00:31
  • @Rajeshwar No, that question only pertains to auto_ptr; shared_ptr can be copied since they use a reference count – SRobertJames May 27 '15 at 00:37
  • For vectors you have to specify the type of object they will be holding. In your case it will be `boost::shared_ptr` and then you could use `get` to pull out the raw pointer – Rajeshwar May 27 '15 at 00:41
  • 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. – Yakk - Adam Nevraumont May 27 '15 at 00:54

2 Answers2

4

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
Eiko
  • 25,601
  • 15
  • 56
  • 71
msmith81886
  • 2,286
  • 2
  • 20
  • 27
  • In what way does this demonstrate a vector containing both smart and dumb pointers? – Yakk - Adam Nevraumont May 27 '15 at 00:55
  • You can query the `std::shared_ptr` for the internal dumb pointer using `std::shared_ptr::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. – msmith81886 May 27 '15 at 01:15
  • 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`!), but the above doesn't demonstrate it happening. – Yakk - Adam Nevraumont May 27 '15 at 01:20
1

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.

Rajeshwar
  • 11,179
  • 26
  • 86
  • 158
  • 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". – Yakk - Adam Nevraumont May 27 '15 at 00:55
  • 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. – Rajeshwar May 27 '15 at 00:58
  • 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! – Yakk - Adam Nevraumont May 27 '15 at 01:06
  • 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. – Yakk - Adam Nevraumont May 27 '15 at 01:21