user3335011
user3335011

Reputation: 67

const_pointer_cast of a std::set iterator

I've got a bit of a conundrum here. I am writing a mesh (grid) generator. In doing so, I need to obtain a list of lower dimensional elements from higher dimensional elements (i.e. a "triangle" element is composed of 3 "line" elements). I need the list of unique line elements and I need the parent element to store a pointer to each of its unique child elements.

To this end, I create a std::set of smart pointers to the child elements and try to insert each child element to the list. Every time I try to insert an element I ask for a pair containing an iterator to the pre-existing element and a boolean specifying whether or not the element has been inserted.

The problem is that std::set (and map) return constant iterators to the pre-existing element. However, I need to give the parent element of the element that I failed to insert a non-constant pointer to the pre-existing element. So I use const_pointer_cast<> to cast the constant iterator to a non-constant one.

Is there a better way of going about this? Doing a const_pointer_cast() is probably not ideal. Is there something that I should be using for this application instead of std::set?

Edit: here's the function:

template<class T1, class T2>
int getUniqueSubelements(std::set<std::shared_ptr<T1>, elGreater>& elements,
                         std::set<std::shared_ptr<T2>, elGreater>& childels)
{
    typedef std::shared_ptr<T2> child_ptr;

    std::pair<typename std::set<child_ptr, elGreater>::iterator, bool> ret;

    for (auto parit = elements.begin(); parit != elements.end(); ++parit)
    {
        (*parit)->generateChildren();

        const std::vector<child_ptr>& children = (*parit)->getChildren();

        for (int i = 0; i < children.size(); i++)
        {
            ret = childels.insert(children[i]);

            if (ret.second == false)
            {
                child_ptr temp = std::const_pointer_cast<T2>(*ret.first);
                bool orient = elOrientation(children[i], temp);
                children[i]->swapInParent(temp, orient);
            }
        }
    }
    return 1;
}

Upvotes: 0

Views: 473

Answers (1)

aschepler
aschepler

Reputation: 72271

No cast at all is needed here.

It's true that std::set<K, Comp>::iterator is the same as std::set<K, Comp>::const_iterator, and that iterator::operator* returns a const K&.

But in your case, this means that the type of *ret.first is const std::shared_ptr<T2>&. This is the analogue of (T2* const), not (const T2*): you can't modify the smart pointer, but you can modify the actual stored object.

So assuming elOrientation is something like

template <typename T>
bool elOrientation(std::shared_ptr<T>, std::shared_ptr<T>);

you can just call elOrientation(children[i], *ret.first).

Upvotes: 0

Related Questions