Question

I have a situation that occurs 5 times in my code, and continues to grow. Basically I have the same switch statement structure every time I need to perform an operation that involves my matrix and its type (which is set dynamically at runtime from files and user input). Here is one such example:

//QTableWidget m_matrix_table;
//cv::Mat m_matrix;
MatrixBoxWidget::MatrixBoxWidget(QWidget *parent) : QWidget(
        parent) {
     ...
     connect(m_matrix_table, &QTableWidget::cellChanged, this,
             &MatrixBoxWidget::updateMatrixValue);
     ...
}

void MatrixBoxWidget::updateMatrixValue(int row, int column) {
    QTableWidgetItem item = m_matrix_table->item(row, column);
    QVariant qvariant = item->data(0);
    int type = m_matrix.type();
    switch (type) {
        case CV_8U:
            m_matrix.at<std::uint8_t>(row, column)
                    = qvariant.value<std::uint8_t>();
            break;
        case CV_8S:
            m_matrix.at<std::int8_t>(row, column)
                    = qvariant.value<std::int8_t>();
            break;
        case CV_16U:
            m_matrix.at<std::uint16_t>(row, column)
                    = qvariant.value<std::uint16_t>();
            break;
        case CV_16S:
            m_matrix.at<std::int16_t>(row, column)
                    = qvariant.value<std::int16_t>();
            break;
        case CV_32S:
            m_matrix.at<std::int32_t>(row, column)
                    = qvariant.value<std::int32_t>();
            break;
        case CV_32F:
            m_matrix.at<float>(row, column)
                    = qvariant.value<float>();
            break;
        case CV_64F:
            m_matrix.at<double>(row, column)
                    = qvariant.value<double>();
            break;
        default:
            assert((false, "unknown type format"));
            break;
    }

}

usually the function signatures (or what ever else I decide to do in the switch cases) are homogenous except for the types in most circumstances, I'm only aiming to fix these cases.

Opencv uses these integers to change the type of a matrix. This is what I'm switching on. What can I do to mitigate this? Or is this kind of boiler plate necessary? Template functions that take another function don't appear to work since they would require all the templates versions of the function anyway, which doesn't get rid of the boiler plate code.

EDIT:

The marked duplicate has actually zero to do with my question. There's not a single template mentioned in either answer, and neither solves my problem.

This is what I'd like to do:

foo<T>(int type, std::function bar) where bar would be templated inside of foo, but that is clearly not possible with current C++ semantics. the problem isn't that I'm using switch statements, its that the pattern is homogeneous across multiple use cases with the same cases.

Was it helpful?

Solution

Well, if you have the same kind of code multiple times, meaning switch on type-code and then use identical code with that type, how about using a template and generic lambda?

template <class F>
auto do_typed(int type, F f) {
    switch(type) {
    case CV_8U:  return f(std::enable_if<true, std::uint8_t>());
    case CV_8S:  return f(std::enable_if<true, std::int8_t>());
    case CV_16U: return f(std::enable_if<true, std::uint16_t>());
    case CV_16S: return f(std::enable_if<true, std::int16_t>());
    case CV_32S: return f(std::enable_if<true, std::int32_t>());
    case CV_32F: return f(std::enable_if<true, float>());
    case CV_64F: return f(std::enable_if<true, double>());
    }
    assert(false);
}

And use it like:

do_typed(m_matrix.type(), [&](auto x){
    using T = typename decltype(x)::type;
    m_matrix.at<T>(row, column) = qvariant<T>();
});

I'm using the trivial type std::enable_if<true, T> to signal the intended type because it is always a trivial empty type, thus not imposing any restrictions on what can be conveyed.

Also, if you have more type-lists and the type-codes are consecutive, it can be easily generalized.

Licensed under: CC-BY-SA with attribution
scroll top