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?
 
     
    