Need efficient way of converting list<A*> to list<const A*>

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • gsBytes
    New Member
    • Sep 2008
    • 4

    Need efficient way of converting list<A*> to list<const A*>

    I am working with a specialized graph class, which has a node class and an edge class. In the node class, there is a list of pointers to each edge. Code that uses the graph must be able to see what edges are contained in a node. This is handled by returning a const reference to a list of edge pointers, i.e:
    Code:
    const list<Edge*>& Node::getEdges() const {
        return edges; // list<Edge*>
    }
    However, I don't like this because code outside the graph can modify the edges through the edge pointers. So, ideally, I want this:

    Code:
    const list<const Edge*>& Node::getEdges() const {
        return edges; // list<Edge*>
    }
    But, this of course won't work because list<const Edge*> is a different type than list<Edge*>. I had been handling this problem with a reinterpret_cas t, which theoretically should work fine since list<const Edge*> and list<Edge*> really are the same type, just with different names. However, this violates strict aliasing rules of g++, so I'm concerned that -03 optimized code may not always work.

    Does anyone know a creative way of converting a list<A*> to a list<const A*> without using a reinterpret_cas t (and without less efficient methods like copying the entire list)?

    I was considering creating my own Java-like Iterator that only returns a const version of each object in the list. Although this would work, it seems like overkill. Any suggestions would be appreciated. Thanks.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Have you considered returning a list<Edge> rather than list<Edge*>& ?

    That would protect the original list.

    Comment

    • gsBytes
      New Member
      • Sep 2008
      • 4

      #3
      I have considered that, but each node already has a list of Edge pointers, and I am trying to avoid having to copy all the data into a new list. I was also trying to eliminate returning a copy of the list, since this occurs in code that is performance critical.

      Also, there are other places in the code with similar problems. For example, consider two classes Base and Derived, where Derived inherits Base. There are places in the code where a class contains a list of Derived pointers, but has a method that needs to return a list of Base pointers.

      Code:
      const list<Base*>& SomeClass::func() const {
          return derivedList; // list<Derived*>
      }
      Again, I was using reinterpret_cas t, but I'm not happy with it. Is there any better way to do this without having to copy the entire list into a new list?

      Comment

      • gsBytes
        New Member
        • Sep 2008
        • 4

        #4
        By the way, just to clarify, I'm not just concerned with changes to the list. I am also trying to avoid changes to the objects that are pointed to by the pointers in the list.

        Comment

        • gsBytes
          New Member
          • Sep 2008
          • 4

          #5
          Any other ideas, before I create my own custom iterator?

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            My last suggestion is to return a list<const Edge*>. That is, if you can return an Edge* you can always assign an Edge* to a const Edge*. Then you add the const Edge* to the list and return the list.

            No there can be no changes to anything pointed at by a const Edge*.

            Comment

            • Patrick Horgan
              New Member
              • Dec 2010
              • 2

              #7
              This doesn't violate strict-aliasing. Things that are compatible types or differ only by the addition of any combination of signed, unsigned, const or volatile are allowed to alias. If you want to know more about strict-aliasing and what it is you can look at my white paper, Understanding C/C++ Strict Aliasing
              or – Why won't the #$@##@^% compiler let me do what I need to do!


              Patrick

              Comment

              Working...