Auto + Exceptions

Auto

std::vector<FaceAppearance>
non_maximum_supression(const std::vector<FaceAppearance>& results)
{
    constexpr float nms_threshold = .4F;
    const auto num_predictions = results.size();
    std::vector<bool> suppressed(num_predictions);
    std::vector<FaceAppearance> result_metadata;

    for (auto i = 0UL; i < num_predictions; i) {
        if (suppressed[i]) {
            continue;
        }
        const auto score = results[i].score;
        const auto ix1 = results[i].bbox.x;
        const auto ix2 = results[i].bbox.x  results[i].bbox.width;
        const auto iy1 = results[i].bbox.y;
        const auto iy2 = results[i].bbox.y  results[i].bbox.height;
        const auto width = results[i].bbox.width;
        const auto height = results[i].bbox.height;

        const auto iarea = (ix2 - ix1  1) * (iy2 - iy1  1);
        cv::Rect2f bounding_box = cv::Rect2f{ix1, iy1, width, height};

        const auto& age = results[i].age;
        const auto& male_prob = results[i].male_prob;
        const auto& landms = results[i].landms;
        result_metadata.push_back(
            FaceAppearance{landms, bounding_box, score, age, male_prob});

        for (size_t j = i  1; j < num_predictions; j) {
            const auto jx1 = results[j].bbox.x;
            const auto jx2 = results[j].bbox.x  results[j].bbox.width;
            const auto jy1 = results[j].bbox.y;
            const auto jy2 = results[j].bbox.y  results[j].bbox.height;

            const auto jarea = (jx2 - jx1  1) * (jy2 - jy1  1);
            const auto xx1 = std::max(ix1, jx1);
            const auto yy1 = std::max(iy1, jy1);
            const auto xx2 = std::min(ix2, jx2);
            const auto yy2 = std::min(iy2, jy2);
            const auto w = std::max(0.F, xx2 - xx1  1);
            const auto h = std::max(0.F, yy2 - yy1  1);
            const auto inter = w * h;
            const auto ovr = inter / (iarea  jarea - inter);
            if (ovr >= nms_threshold) {
                suppressed[j] = true;
            }
        }
    }
    return result_metadata;
}

face_appearance.cc

std::vector<FaceAppearance>
non_maximum_supression(const std::vector<FaceAppearance>& results)
{
    constexpr float nms_threshold = .4F;
    const auto num_predictions = results.size();
    std::vector<bool> suppressed(num_predictions);
    std::vector<FaceAppearance> result_metadata;

    for (auto i = 0UL; i < num_predictions; i) {
        if (suppressed[i]) {
            continue;
        }
        const auto score = results[i].score;
        const auto ix1 = results[i].bbox.x;
        const auto ix2 = results[i].bbox.x  results[i].bbox.width;
        const auto iy1 = results[i].bbox.y;
        const auto iy2 = results[i].bbox.y  results[i].bbox.height;
        const auto width = results[i].bbox.width;
        const auto height = results[i].bbox.height;

        const auto iarea = (ix2 - ix1  1) * (iy2 - iy1  1);
        cv::Rect2f bounding_box = cv::Rect2f{ix1, iy1, width, height};

        const auto& age = results[i].age;
        const auto& male_prob = results[i].male_prob;
        const auto& landms = results[i].landms;
        result_metadata.push_back(
            FaceAppearance{landms, bounding_box, score, age, male_prob});

        for (size_t j = i  1; j < num_predictions; j) {
            const auto jx1 = results[j].bbox.x;
            const auto jx2 = results[j].bbox.x  results[j].bbox.width;
            const auto jy1 = results[j].bbox.y;
            const auto jy2 = results[j].bbox.y  results[j].bbox.height;

            const auto jarea = (jx2 - jx1  1) * (jy2 - jy1  1);
            const auto xx1 = std::max(ix1, jx1);
            const auto yy1 = std::max(iy1, jy1);
            const auto xx2 = std::min(ix2, jx2);
            const auto yy2 = std::min(iy2, jy2);
            const auto w = std::max(0.F, xx2 - xx1  1);
            const auto h = std::max(0.F, yy2 - yy1  1);
            const auto inter = w * h;
            const auto ovr = inter / (iarea  jarea - inter);
            if (ovr >= nms_threshold) {
                suppressed[j] = true;
            }
        }
    }
    return result_metadata;
}

face_appearance.cc

Exceptions

Exceptions

  • 117 throws
  • 18 non-runtime_errors thrown
  • Thrown types:
    1xsystem_error, 2xlogic_error, 3xInvalidSha256, 3xInvalidCRC32, 6xSQLError, 1xDownloadError
  • 17 catches in total:
    1xruntime_error, 6xexception, 7x'...', 2xnlohman, 1xSQLError

Consequences

  • Effectively: We don't use exceptions
  • If we do, we throw generic types, that bubble all the way up
  • We are not even aware in code when errors should be handled
  • One consequence, error messages to edge look like this:
     

 

  • One place where we do extensive handling: HTTP.
    Enforced via result type:
    std::variant<HttpDownloadResult, HttpRequestError>
Error occured [Error: [json.exception.type_error.302]
type must be number, but is string]

Proposal:

  • Let's see if we get value from going into the direction of using absl::StatusOr
A statusor library containing the absl::StatusOr<T> class template for use in returning either an absl::Status error or an object of type T. (This StatusOr<T> abstraction is similar to the C++ proposal for std::expected.)

https://abseil.io/docs/cpp/guides/status#overview-of-abslstatus

Auto

By technology