Rimuovere le istruzioni switch duplicate causate dal non conoscere il tipo in fase di compilazione della matrice opencv?

1

Ho una situazione che si verifica 5 volte nel mio codice e continua a crescere. Fondamentalmente ho la stessa struttura di switch statement ogni volta che ho bisogno di eseguire un'operazione che coinvolge la mia matrice e il suo tipo (che è impostato dinamicamente in fase di runtime da file e input dell'utente). Ecco uno di questi esempi:

//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;
    }

}

in genere le firme delle funzioni (o qualsiasi altra cosa decida di fare nei casi di switch) sono omogenee, tranne che per i tipi nella maggior parte dei casi, mirano solo a correggere questi casi .

Opencv usa questi numeri interi per cambiare il tipo di una matrice. Questo è ciò che sto accendendo. Cosa posso fare per mitigare questo? O è necessario questo tipo di piastra per la caldaia? Le funzioni dei modelli che svolgono un'altra funzione non sembrano funzionare in quanto richiedono comunque tutte le versioni dei modelli della funzione, il che non elimina il codice della piastra della caldaia.

EDIT:

Il duplicato contrassegnato ha effettivamente a che fare con la mia domanda. Non c'è un singolo modello menzionato in nessuna delle due risposte, e nessuno dei due risolve il mio problema.

Questo è quello che mi piacerebbe fare:

foo<T>(int type, std::function bar) dove la barra verrebbe inserita all'interno di foo, ma ciò non è chiaramente possibile con la semantica C ++ corrente. il problema non è che sto usando le istruzioni switch, è che il pattern è omogeneo in più casi d'uso con gli stessi casi .

    
posta opa 27.07.2018 - 17:16
fonte

1 risposta

9

Bene, se hai lo stesso tipo di codice più volte, cioè attiva il codice-tipo e poi usi un codice identico con quel tipo, che ne dici di usare un modello e un lambda generico?

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);
}

E usalo come:

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

Sto usando il tipo banale std::enable_if<true, T> per segnalare il tipo voluto perché è sempre un tipo banale vuoto, quindi non impone alcuna restrizione su ciò che può essere trasmesso.

Inoltre, se hai più elenchi di tipi e i codici tipo sono consecutivi, può essere facilmente generalizzato.

    
risposta data 27.07.2018 - 17:57
fonte

Leggi altre domande sui tag