7

Possible Duplicate:
Elegant solution to duplicate, const and non-const, getters?

Say I have a c++ class with a memberfunction which is overloaded for const, like this:

        Type*  DoSomething();
const   Type*  DoSomething() const;

If this is a larger, more complex member, how does one prevent having to write the same code twice ? Can't call any non-const functions from the const one. And calling the const version from the non-const one results in a const pointer wich has to be cast to non-const (wich smells a bit imo).

Community
  • 1
  • 1
Unimportant
  • 2,076
  • 14
  • 19
  • The cast is the way Scott Meyers suggests in Effective C++ as do various dupes of this question on SO. – AJG85 Jul 25 '12 at 18:13

3 Answers3

8

You can delegate to a template static member function, as in:

class Widget
{
    Type member;

    template<typename Result, typename T>
    static Result DoSomethingImpl(T This)
    {
        // all the complexity sits here, calculating offsets into an array, etc
        return &This->member;
    }

public:
            Type*  DoSomething() { return DoSomethingImpl<Type*>(this); }
    const   Type*  DoSomething() const { return DoSomethingImpl<const Type*>(this); }
};

In C++11, you can even get rid of the non-inferred template argument, with:

static auto DoSomethingImpl(T This) -> decltype(This->member)
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Interesting twist. I have not see the template(ing) of the private method before. – Martin York Jul 25 '12 at 20:50
  • Looks like Steve Jessop mostly described this in his answer [here](http://stackoverflow.com/a/858893/103167), although I think a private static member function is cleaner. – Ben Voigt Jul 25 '12 at 20:55
  • @Ben i don't see the point of using a static member function. why not we use a const private member function? – ggg Aug 07 '12 at 12:28
  • 1
    @ggg: I think you failed to understand the original question. What is the type of `member` inside a const member function? – Ben Voigt Aug 07 '12 at 14:44
  • @BenVoigt you can make it mutable – ggg Aug 08 '12 at 00:02
  • 1
    @ggg: But the member isn't supposed to be changed from `const` member functions. `mutable` isn't appropriate here, it's just a hack, and this answer avoids the problem cleanly. – Ben Voigt Aug 08 '12 at 00:04
1

You did it once, and to do it second time with a const attribute on the class, you can use const_cast:

class Foo
{
          Type*  DoSomething()
  {
    // Lots of stuff
  }
  const   Type*  DoSomething() const
  {
    return const_cast<Foo*>(this)->DoSomething();
  }
}
Roman R.
  • 68,205
  • 6
  • 94
  • 158
1

Use the template method pattern to extract the common code from them. Eg.

inline const T* prev(size_t i) const
{
    return &FBuffer[ AdjustIndex(i) ];
}

inline T* prev(size_t i)
{
    return &FBuffer[ AdjustIndex(i) ];
}

inline size_t AdjustIndex( size_t i ) const
{
    return Math::ModInt( static_cast<int>( FHead ) - 1 - i, static_cast<int>( FBuffer.size() ) );
}

This technique can be applied in many cases (but not all of them, i.e. if the behavior differs significantly).

Sergey K.
  • 24,894
  • 13
  • 106
  • 174