Forwarding a shared_ptr without class declaration

2020-08-14 07:42发布

问题:

NOTE: I've found the source of the error is not actually related to the shared_ptr, just cleverly disguised as such in the error message. Thus the below is basically nonsense (not the answers, they're fine)

--

I'm having some trouble using a shared_ptr (boost's at the moment) where I need to simply forward a pointer to another function. Using native pointers the intervening function would not need to have access to the definition of the class, but using smart_ptr's it appears it does. Is there any way to avoid this?

For example, given a target function:

void func( shared_ptr<SomeClass> const & obj )

The const & takes care of part of the problem, but say we have a getter class which obtains the object for some other class, like:

shared_ptr<SomeClass> someClassInstance();

And here is where I'd like to simply assemble arguments and forward to the target function:

func( someClassInstance() );

With a plain pointer this point in the code could simply use a forward declaration of SomeClass, but with a smart_ptr it needs to have the full definition (presumably as the smart_ptr might need to delete the class).

Now, if someClassInstance were to return a const & this problem would actually go away as the intervening code would not be copying any objects. However, the getter function must return the copy for thread-safety reasons.

Is there anyway I can achieve this type of smart pointer parameter forwarding without needing the class definition? That is, can I use smart pointers in the same fashion as I would a traditional pointer in this circumstance.

--

UPDATE: Writing a small test the answers are correct that a forward declaration is enough. Yet GCC is still complaining in one situation. I'm going to have to figure out exactly what is causing it to fail (in this particular situation).

Do I close this question for now, or what?

回答1:

You need at least a forward declaration for T for every mention of shared_ptr<T>.

Only if you use unary shared_ptr::operator* and shared_ptr::operator->, the full thing is needed. Under the hood, shared_ptr uses a mix of compiletime- and runtime-polymorphism, making this possible. See also this question to learn about the "magic".

Example:

// frob.h
#ifndef FROB_H
#define FROB_H

#include <shared_ptr>

class Foo;
void grind (std::shared_ptr<Foo>);

#endif

Note that the canonical way to pass shared_ptr is by value (i.e. remove the const&).



回答2:

Yes, shared pointers are specifically designed to work with incomplete types (a killer feature IMO). They require only a forward declaration of a class, not the class definition. From the Boost documentation:

Note that scoped_ptr requires that T be a complete type at destruction time, but shared_ptr does not.

You can find a discussion of how this works here.

Since shared pointers should work with incomplete types, can you give us a specific (minimal) example in which this doesn't work for you?



回答3:

It seems that explicit forward declaration is not always required:

using PtrX = std::shared_ptr<class X>;
using PtrW = std::weak_ptr<X>;

Here class X inside template argument does the magic.



标签: c++ boost c++11