4

I keep running into an error that no matching constructor for initialization of 'std::shared_ptr<void>' which makes sense, but I don't know where to begin.

Here is what I'm working with.

#include <memory>                                                                                                                                                             

struct Container {                                                             
  int type;                                                                    
  std::shared_ptr<void> payload;                                               

  Container(int t, const void *p) : type(t), payload(p) { }                    
};                                                                             

int main() {                                                                   
  return 0;                                                                    
}

I'm trying to make a generic container using a shared_ptr with type of void. I was going to do a switch on the type and then just cast the payload into the appropriate type.

I figured I could just do something like Container ctn(1, new Data()); but I think I might have that wrong as well.

Thanks.

Leroy
  • 544
  • 3
  • 14
  • 4
    Just be happy that this problem prevents you going forward with that design. As an example, Bertrand Meyer decided to not support enumeration types in Eiffel, just to prevent your design. It's that bad, an extreme anti-pattern, the very opposite of object-oriented. Now forget about `void*` pointers. Use a standard library container. – Cheers and hth. - Alf Nov 10 '14 at 21:31
  • `I'm trying to make a generic container using a shared_ptr` Ok. `with type of void` That has been solved with templates -- drop the `void*`. C++ isn't `C`. – PaulMcKenzie Nov 10 '14 at 21:35

3 Answers3

2

You're trying to initialise a pointer to void with a pointer to const void, which is indeed illegal. The "smartness" of the pointer does not matter, this would fail for ordinary pointers as well.

You either need to change the type of payload to std::shared_ptr<const void>, or (probably more what you actually want) change the type of p to void*.


Note, however, that while this will technically solve the immediate problem, it can introduce a more fundamental one. Under this design, payload will know nothing about the actual type to which it points, so it will not call a destructor of Data when the last reference goes out. You should probably rethink the entire design to use suitably typed pointers.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • It was my understanding from the top answer in http://stackoverflow.com/questions/5450159/type-erasure-techniques that shared_ptr calls the correct destructor. – Leroy Nov 10 '14 at 21:38
  • 6
    @Grashlok It calls the correct destructor, *if you tell it which one to call* by constructing it with a pointer to the correct type. In your case the type information is lost before it even got to the `shared_ptr` constructor. – T.C. Nov 10 '14 at 21:39
2

Note up front: Take a look at Boost.Any, which probably does what you want.

That said, you can't just store a void pointer in a shared_ptr, because delete on a void pointer doesn't work. For that reason, shared_ptr overloads its constructor in order to create the right deleter for the actual type of the pointer. You could do the same using a template constructor:

struct Container {
    int type;
    std::shared_ptr<void> payload;
    template<typename T>
      Container(int t, T* p) : type(t), payload(p) { }
};

Now, have fun finding out why this is a recipe to shoot yourself in the foot.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
1

You can use a template and write shared_ptr<T>

If you don't want to use a template then you should define an abstract class and all the items you will put in the container should be derived from that class (as a java interface)

But I strongly discourage you to use void*

dynamic
  • 46,985
  • 55
  • 154
  • 231