Question

I have two classes whose functions take typedefed pointers to eachother as return values and parameters. I.e.:

class Segment;

class Location : public Fwk::NamedInterface {
  public:
    // ===== Class Typedefs =====
    typedef Fwk::Ptr<Location const> PtrConst;
    typedef Fwk::Ptr<Location> Ptr;
    // ===== Class Typedefs End =====
    void segmentIs(Segment::Ptr seg);
    /* ... */
}

and class Location;

class Segment : public Fwk::NamedInterface {
  public:
    // ===== Class Typedefs =====
    typedef Fwk::Ptr<Segment const> PtrConst;
    typedef Fwk::Ptr<Segment> Ptr;
    // ===== Class Typedefs End =====
    void locationIs(Location::Ptr seg);
    /* ... */
 }

This understandably generated linker errors...which the forward declarations of the respective classes don't fix. How can I forward declare the Ptr and PtrConst typedefs while keeping these typedefs internal to the class (i.e. I would like to write Location::Ptr to refer to the location pointer type)?

Thanks folks!

Was it helpful?

Solution

There's a hidden metafunction in there which takes a type T and returns Fwk::Ptr< T >. You have implemented this metafunction twice. Implementing it inside the classes introduces a false dependency of the metafunction upon the classes.

To remove this false dependency, implement the metafunction before anything else.

template< typename T >
using FwkPtr = Fwk::Ptr< T >;

(Edit: here is a C++03 style metafuction.

template< typename T >
struct FwkPtr {
    typedef Fwk::Ptr< T > type;
};

Then you would refer to FwkPtr< Segment >::type, or if the metafunction is applied to a template parameter or result thereof, typename FwkPtr< T >::type.)

If in the future Segment and Location are templated so their Ptr members could be something else, then the problem goes away because of delayed evaluation. But the fix still works, and it's still conceptually valid.

You might (ultimately) have the metafunction compute something else, or have more than one metafunction. The point is that you don't need the entire class to do it, and it's not a functionality encapsulated by the class.

On the other hand, if the arguments will always certainly be Fwk::Ptr< Segment > and Fwk::Ptr< Location >, you can just specify them that way and sidestep the issue.

OTHER TIPS

You can't access a type that hasn't been declared

class Location : public Fwk::NamedInterface {
  public:
    // ===== Class Typedefs =====
    typedef Fwk::Ptr<Location const> PtrConst;
    typedef Fwk::Ptr<Location> Ptr;
    // ===== Class Typedefs End =====

    // this is illegal
    void segmentIs(Segment::Ptr seg);
};

Instead, try typedef'ing outside the class.

class Segment;
class Location;
typedef Fwk::Ptr<Segment>  SegmentPtr;
typedef Fwk::Ptr<Location> LocationPtr;

class Location : public Fwk::NamedInterface {
  public:
    // ===== Class Typedefs =====
    typedef Fwk::Ptr<Location const> PtrConst;
    // ===== Class Typedefs End =====
    void segmentIs(const SegmentPtr& seg);
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top