1

I'm wondering about one thing. I've got class which has 1 overloaded member function:

class A{
    public:
    class const_iterator{};
    class iterator : public const_iterator{};
    iterator find(const K &key);
    const_iterator find(const K &key) const;
};

Ad. iterator is inheriting from const_iterator, but it isn't adding anything.

What I want to do is, inside normal find call const find. Something like this:

typename A::iterator A::find(const K &key){
     const_iterator it(find(key));
     return (*(iterator*)&it);
}

I don't need different implementation of non-const find ATM. Is it possible to do something like this? Because now I'm getting into infinite loop, adding "A::" before find isn't changing anything.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Michał Dębski
  • 527
  • 4
  • 16
  • Possible duplicate: http://stackoverflow.com/questions/123758/how-do-i-remove-code-duplication-between-similar-const-and-non-const-member-func – Vincenzo Pii Nov 18 '12 at 13:53

2 Answers2

2
const_cast<const A*>(this)->find(key);
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • @Aardvark - good point. I changed `static_cast` to `const_cast`. Thanks. – Pete Becker Nov 18 '12 at 13:41
  • Why don't we use `static_cast` or `dynamic_cast` or a regular cast? Why does `const_cast<>` have to be used? – David G Nov 18 '12 at 13:47
  • @David Because we change the `const`-ness of the object, nothing more. Furthermore, `dynamic_cast` would be totally wrong here since it only applies to casting within an inheritance hierarchy (and even then only when we’re not sure whether the cast will succeed, and handle the resulting null value accordingly), which isn’t the case here. – Konrad Rudolph Nov 18 '12 at 13:53
  • @KonradRudolph Thanks. I'm kind of confused with those `---_cast<>` functions. – David G Nov 18 '12 at 13:54
  • 1
    `const_cast` changes only the const-ness of the argument. That's the narrowest conversion that gets to the right type. `static_cast` also works, but it can do more than just changing const-ness, so shouldn't be used here. The risk is that a more powerful cast can change other aspects of the type; in a simple case like this one it's not likely, but in more complicated situations a more powerful cast could mask a coding error. In general, use the least-powerful cast that does what's needed. – Pete Becker Nov 18 '12 at 13:54
2

In general, there’s no clean solution for this, unfortunately.

You can call the overloaded find by simply casting this to A const* – but the result will be of the wrong type (const_iterator rather than iterator) and there may not be a conversion between these in the general case (your (*(iterator*)&it) won’t work in your case).

But of course, in your special case, since you defined the two classes, you can define such a conversion by adding an appropriate constructor to iterator:

class iterator : public const_iterator {
    iterator(const_iterator const& other) { 
        // Construct …
    }
};

Then you can re-write your non-const find implementation as follows:

A::iterator A::find(const int &key){
    const_iterator it(const_cast<A const*>(this)->find(key));
    return static_cast<iterator>(it);
}

Incidentally, note the absence of typename in the return type. Since A::iterator isn’t a dependent name, you don’t need (and, at least in C++03, are not allowed to) use typename here.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • thanks a lot, that worked, i need typename because there are templates and so on, also it works with that simple downcasting the pointer, I didn't have to define conversion(maybe because this inhering is mostly only name change and it isn't implementing anything new) – Michał Dębski Nov 18 '12 at 14:34
  • @MichałDębski No, you *do* need to define the conversion. There is no automatic downcast from base class to derived class. Your pointer cast is forbidden and yields undefined behaviour. – Konrad Rudolph Nov 18 '12 at 14:38