4

Suppose I have a struct that has a name and some value associated with it:

struct Season {
  std::string name;
  // Mean temperature over the season
  double meanTemperature;
  // Days since the start of year when it's strongest
  float strongestAt;
  // Fraction of a year it applies to, compared to other seasons
  float yearFraction;
}

This class describes a season per year. Suppose I have a collection of them, which fills in the entire year:

// made up method that is supposed to find a season (I don't use it in real code)
int findIndex(const std::vector<Season>& in, std::function<bool(const Season&)>);
class SeasonCollection
{
public:
  const Season* GetSeason(const std::string& name) const
  {
    const int index = findIndex(_seasons, [name](const Season& s) { return s.seasonName == name; });
    return index != -1 ? &_seasons[index] : nullptr;
  }
  Season* GetSeason(const std::string& name)
  {
    const int index = findIndex(_seasons, [name](const Season& s) { return s.seasonName == name; });
    return index != -1 ? &_seasons[index] : nullptr;
  }
private:
  //! Settings for seasons
  std::vector<Season> _seasons;
};

In that collection you can see that I need to get both const Season* and Season*. That's because in some contexts, the collection is meant to be read-only and in some others, it is writeable.

There will also be other ways of getting a season, such as day of the year (eg. Christmas day 24.12). I want to have a const getter for each method of getting them, but I also do not want to copy-paste each of them and just add const.

What's the best approach?

0

2 Answers 2

7

I hate to say it, but const_cast. What you do is make and call the const getter, and just remove the const that it returns since you know you are in a non-const object inside the non const getter. That would look like

  const Season* GetSeason(const std::string& name) const
  {
    const int index = findIndex(_seasons, [name](const Season& s) { return s.seasonName == name; });
    return index != -1 ? &_seasons[index] : nullptr;
  }
  Season* GetSeason(const std::string& name)
  {
    return const_cast<Season*>(const_cast<SeasonCollection const *>(this)->GetSeason(name));
    //     ^ remove the const^ ^ add const to call the const getter     ^^call const getter^
  }
Sign up to request clarification or add additional context in comments.

2 Comments

I was hoping this will not be the only answer.
@TomášZato-ReinstateMonica Why is that? like goto, const_cast actually has valid use cases and this is one of them.
5

From Scott Meyers book, Effective C++, item 4:

When const and non-const member functions have essentially identical implementations, code duplication can be avoided by having the non-const version call the const version.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.