How to neatly write two functions - one for checking if a solution exists, and another one for getting all solutions?

Viewed 66

The obvious way is to just write two functions, but then they are almost identical. What I'm doing now is a function template with the return type (either bool or vector<something>) as the argument

template<typename ReturnType>
ReturnType foo(...){
    constexpr bool return_bool = std::is_same<ReturnType, bool>::value;
    ResultType results; //hopefully, the compiler takes it out in the bool case 

And the plan is to use if constexpr(return_bool) when needed. But then I get this reoccurring piece of code

ReturnType result = foo<ResultType>(...);
if constexpr(return_bool){
    if(result) return true;
}else std::copy(result.begin(), result.end(), std::back_inserter(results));

The return statement makes it hard to use standard anti-repetition techniques. I could use macros but then perhaps the repetition is better. Getting either all solutions or just the information whether one exists seems like a fairly general problem, is there a better way to do it?

I should've added that the function is performance-critical in the "does a solution exist?" case. That's why I want to have another version there and also why I don't want any costly abstractions.

1 Answers

You want two opposite features :

  1. Reusing one solution in the other to avoid replication
  2. Having an optimized version for solutionExists() to avoid a full result search

You didn't specify what is the solution your function returns, so I will explain why you can't have both using a simple example : your function is returning the number of ocurences of 0 in a vector of integers.

The function returning all solutions would look like this :

int GetNumberOfOccurencesOf0(const vector<int>& data)
{
  int occurences = 0;
  for (int i : data)
  {
    if (i == 0)
      ++occurences;
  }
  return occurences;
}

If you are not concerned about performance, your function for returning if there is a solution can be :

bool AreThereOccurencesOf0(const vector<int>& data)
{
  return (GetNumberOfOccurencesOf0(data) > 0);
}

Note that there is no code duplication but the solution is not optimal : the data vector is iterated entirely. If you want an optimized solution, it would look like this :

bool AreThereOccurencesOf0(const vector<int>& data)
{
  for (int i : data)
  {
    if (i == 0)
      return true;
  }
  return false;
}

If your problem requires an optimized version of solutionExists(), you should write it and it should not need to reuse code from the getAllSolutions() function.

Related