2

My question is a bit vague and that is at least partially intentional. I'm looking for early advice about interface design, future expansion and easy to test-interfaces and not too much about exact code. Although, if it's a solution/advice that applies especially to C++(17), then that's perfect.

I've a simulation that solves a hard combinatorial problem. The simulation propagates step by step to a solution. But sometimes, a step is a dead end (or appears as such). For example, in the pseudo code below, the while loop propagates the simulation by feeding it with pieces. There there can be a case where a 'Piece' can not be used to propagate the simulation. E.g. it's to expensive, it's a piece that simply does not fit or the for what ever reason. Failure is a normal behaviour that can arise an no reason to abort.

while(!allNotHandledPieced.empty())
{
  auto nextPiece = allNotHandledPieces.back();
  allNotHandledPieces.pop_back();
  auto status = simulation.propagate(nextPiece);
  if(status == 0)
    next; // ok
  else if (status == 1)
    dropPieceDueToTooBadStatus();
}

Actually, for the 'simulation' it doesn't matter why it failed. The state is still valid, there is no problem with using another piece, it can just continue. But later, I might see the need to know why the 'propagate' method failed. Then it might make sense to have a meaningful return value on failure.

Is there a good way to return 'failure'? Is there a best practice for situations like this?

cpplearner
  • 13,776
  • 2
  • 47
  • 72
dani
  • 3,677
  • 4
  • 26
  • 60
  • 1
    Have you heard of execptions? – davidhigh Dec 20 '17 at 23:14
  • 2
    std::optional in C++17 or boost::optional – Cong Ma Dec 20 '17 at 23:38
  • The use of the `throw` keyword. – Jake Freeman Dec 20 '17 at 23:41
  • This is exactly the kind of exceptional situation that exceptions are designed to handle. https://stackoverflow.com/questions/8480640/how-to-throw-a-c-exception – Jive Dadson Dec 20 '17 at 23:41
  • On way is exception handling. The other is returning a `Result` object, which could contain all information about the result. If everything went fine, it can contain the result, if failure, it can contain the reason. C++17 has `[[nodiscard]]`, so it is harder to forget to check a result. – geza Dec 21 '17 at 00:11
  • https://isocpp.org/blog/2012/12/systematic-error-handling-in-c-andrei-alexandrescu – Henri Menke Dec 21 '17 at 00:14
  • I did considered exceptions but i think it's not really a good fit. I use exceptions as an way to prevent abnormal behaviour, failure in this case is not abnormal. It might be unlikely or occur seldom, but it's absolutely possible that a `Piece` does not fit and finding that out is part of the game. – dani Dec 21 '17 at 10:55

1 Answers1

1

From what I can gather, it seems like neither exceptions or "returning" are appropriate for your situation. In your question you talk about "returning a result" but your particular code example/use case suggests that that the algorithm should not halt or be interrupted if a "bad piece" is used. Both exceptions and "returning" from a function will result in more complex control flow, and in some cases, more complex state handling depending on how you deal with exceptions.

If you choose the exception route, I suggest modeling your "reporting" classes after system_error.

If you choose a non-control flow route, I suggest pushing an error code and other meta data about the piece (if the piece itself is too expensive to copy around) into another data structure where it can be consumed.

What you choose to do depends on whether or not the bad piece requires immediate action. If it doesn't, exceptions are not the way to go since that implies it needs to be handled at some point.