Trying to cast QPointer<Type1> to QPointer<Type2> with no joy



  • Hello again everyone,

    I have run into another stumbling block for which I am unable to find any help on Google or this forum.

    What I am trying to do is keep a list of pointers of various types in a QList. This is how I have it set up:

    In the Linker.h file
    @
    enum LinkType
    {
    LinkTypeA,
    LinkTypeB,
    LinkTypeC,
    };

    [...]

    QList< QPair< LinkType, QPointer< QObject > > > m_linkList;
    @

    In the Linker.cpp file
    @
    void Linker::addLink(ClassA* a )
    {
    QPair< LinkType, QPointer< QObject > > pair;
    pair.first = LinkTypeA;
    pair.second = (QObject*)a;
    if(!m_linkList.contains( pair ) )
    {
    m_linkList.append( pair );
    }
    }

    void Linker::addLink( LinkingClassB* link )
    {
    [Same as above]
    }

    void Linker::addLink( LinkingClassC* link )
    {
    [Same as above]
    }

    QList< QPointer< ClassA > > Linker::classALinks()
    {
    QList< QPointer< ClassA > > links;
    for( int linkIndex = 0; linkIndex < m_linkList.count(); linkIndex++ )
    if( m_linkList[ linkIndex ].first == LinkTypeA)
    links.append( (const QPointer < ClassA >)m_linkList[ linkIndex ].second );

    return links;
    }

    QList< QPointer< ClassB > > Linker::classBLinks()
    {
    [Same as above]
    }

    QList< QPointer< ClassC > > Linker::classCLinks()
    {
    [Same as above]
    }
    @

    Classes A, B, and C all descend from QObject. Essentially, I want to store pointers to all objects that are linked to the linker class and keep track of their types based on whatever enum value is contained in the QPair along with the pointer to the object itself. Then, when I retrieve the list of pointers to ClassA type objects I want to cast them back to their original type and add them to the list that is eventually returned. There are no mandatory links and m_linkList could contain many links or none at all.

    The problem that I am running into is that I cannot cast them back to their original type. I keep getting compiler errors such as:

    @
    1>.\Linker.cpp(345) : error C2440: 'type cast' : cannot convert from 'const QPointer<T>' to 'const QPointer<T>'
    1> with
    1> [
    1> T=QObject
    1> ]
    1> and
    1> [
    1> T=ClassA
    1> ]
    1> No constructor could take the source type, or constructor overload resolution was ambiguous
    @

    I have tried several ways to try to type cast the QObject pointer back to a ClassA pointer and still to no avail.

    Could anyone enlighten me on the subject as to what I may be doing wrong?

    Also, any criticism on the design is welcome. If anybody has a better method to be able to achieve the same goal then please share.



  • Few advices:

    1. use QHash< QObject*, LinkType > instead of monstrous QList< QPair< LinkType, QPointer< QObject > > >, it should be faster.
    2. use typedefs. Like
      @typedef QPointer< QObject > QObjectPointer;
      typedef QPair< LinkType, QObjectPointer > QOPPair; // or more relevant name
      typedef QList< QOPPair > QOPPairList;
      QOPPairList m_linkList;
      @
      It will make your code contain less angle brackets :-)

    Did you try to use
    @QPointer< ClassA > classAPointer( qobject_cast< ClassA* >( qObjectPointer.data() ) );@
    ?



  • Hello p-himik,

    Thank you for your prompt response.

    I will go ahead and try a few of your suggestions. I figured a QHash would be inappropriate for this situation where I don't really have a key, value pair with a unique key. However, after giving it some additional thought, I see that I can use the pointer as the key because each pointer should be unique.

    I'll post back later for an update.



  • This is what I finally ended up doing:

    In the Linker.h file:

    @
    QMultiHash< LinkType, QPointer< QObject > > m_linkList;
    @

    I kept the original enum structure from my first post.

    In the Linker.cpp file:

    @
    // Get the total number of links to this object
    int Linker::totalLinkCount() const
    {
    return m_linkList.count();
    }

    [...]

    // Get the number of links to object A
    int Linker::classALinkCount() const
    {
    return m_linkList.count( LinkTypeA );
    }

    [...]

    // Get a list of all links to object A
    QList< QPointer< ClassA > > Linker::classALinks()
    {
    QList< QPointer< QObject > > linkList = m_linkList.values( LinkTypeA );
    QList< QPointer< ClassA > > ptrList;
    for( int linkIndex = 0; linkIndex < linkList.count(); linkIndex++ )
    {
    QPointer<ClassA> ptr( qobject_cast<ClassA*>( linkList[ linkIndex ].data() ) );
    ptrList.append( ptr );
    }
    return ptrList;
    }

    [...]

    // Add a link to object type A
    void Linker::link( ClassA* a )
    {
    QPointer<QObject> ptr( qobject_cast<QObject*>( a ) );
    if(!m_linkList.contains( LinkTypeA, ptr ) )
    {
    m_linkList.insert( LinkTypeA, ptr );
    a->addLink( this );
    }
    }

    [...]

    @

    Equivalent functions exist for Classes B and C and so forth with an overloaded function signature for link().

    This has worked flawlessly for me and the QMultiHash allows me to use duplicated keys with the built-in functions allowing me to count how many of each key exists in the QMultiHash.

    By upcasting my pointers to QObject* I can store all of my links in a single list while keeping track of there types. This way I don't create several unused lists for links to classes B and C if only links to class A exist.

    I really enjoyed doing this part of the project and I want to thank p-himik for the feedback and recommendations.



  • You can rewrite Linker::classALinks() (a little shorter and faster implementation):
    @QList< QPointer< ClassA > > Linker::classALinks()
    {
    QList< QPointer< ClassA > > ptrList;
    foreach( const QPointer< QObject >& p, m_linkList.values( LinkTypeA ) )
    {
    ptrList.append( qobject_cast<ClassA*>( p.data() ) );
    }
    return ptrList;
    }@



  • Once again p-himik, you have been a great help to me. I have updated my code to include that little optimization. I am still not as familiar with the Qt library as I would like to be and so I miss the foreach macro.

    Thank you very much.



  • You're welcome :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.