0

I am attempting to make a generic class, which conditionally calls a function based on the number of parameters supplied to the class. I've been using std::enable_if, but to no avail.

I have tried a variety of different things using three functions (for 2 optional class parameters). I have read many different posts here on stack overflow, which is how I got to what I am currently using, however I am still getting errors.

#include <qsqldatabase.h>

template<class EditorDialog, typename FirstOpt = void, typename SecondOpt = void>
class GenericItemDelegate : public QItemDelegate {
public:
    explicit GenericItemDelegate( QSqlDatabase &connection, QObject *parent = 0 ) : QItemDelegate( parent ), connection( connection ) {}
protected:
    QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const override {
        return createEditorHidden( parent );
    }
    void setEditorData( QWidget *editor, const QModelIndex &index ) const override {
        EditorDialog *dialog = static_cast<EditorDialog *>( editor );
        dialog->loadData( index.data( Qt::ItemDataRole::UserRole ) );
    }
    void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override {
        EditorDialog *dialog = static_cast<EditorDialog *>( editor );
        if ( dialog->result() == QDialog::Accepted ) {
            model->setData( index, QVariant::fromValue( dialog->getData() ) );
        }
    }
private:

    template<typename f = FirstOpt, typename s = SecondOpt, typename std::enable_if<std::is_void<f>::value && std::is_void<s>::value, QWidget *>::type = true>
    QWidget *createEditorHidden( QWidget *parent ) const {
        return new EditorDialog( connection, parent );
    }
    template<typename f = FirstOpt, typename s = SecondOpt, typename std::enable_if<!std::is_void<f>::value && !std::is_void<s>::value, QWidget *>::type = true>
    QWidget * createEditorHidden( QWidget * parent ) const {
        return new EditorDialog( connection, parent, FirstOpt );
    }
    template<typename f = FirstOpt, typename s = SecondOpt, typename std::enable_if<!std::is_void<f>::value && !std::is_void<s>::value, QWidget *>::type = true>
    QWidget * createEditorHidden( QWidget * parent ) const {
        return new EditorDialog( connection, parent, FirstOpt, SecondOpt );
    }


    QSqlDatabase connection;
};

What I am currently getting with the above is error C2672: 'GenericItemDelegate<CreateFormulaDialog,void,void>::createEditorHidden': no matching overloaded function found which does not make sense to me, since (in this case) both template parameters are void.

Effectively, in the end, I would want objects created with GenericItemDelegate<CreateFormulaDialog> to call the first template function, GenericItemDelegate<CreateFormulaDialog, true> to call the second template function, and GenericItemDelegate<CreateFormulaDialog,true,false> to call the third.

Hopefully I'm making sense. I've spent the last few hours working on this, and my brain is just not working anymore.

ChrisMM
  • 8,448
  • 13
  • 29
  • 48
  • Sometimes a plain #ifdef works better than all type trait bells and whistles. – Michael Chourdakis May 15 '19 at 17:44
  • Did you have a look at what SFINAE can do for you? – πάντα ῥεῖ May 15 '19 at 17:44
  • I don't see the reason in doing this in compile-time. Try plain `if` statements, member variables and a constructor. You're doing Qt, not a nuclear power plant. – LogicStuff May 15 '19 at 17:47
  • Because it's generic, the class which it's using (EditorDialog) can have different constructors. It is intended to work with any class passed. With simple if statements, some constructors might not meet the requirements of having the optional second and third parameters, or they could be different types all together. The example I gave is all one class (CreateFormulaDialog), but it should be able to work with other classes, which take different type and number of parameters to its constructors. I have also looked at the post this is marked as a duplicate of, but it does not seem to help. – ChrisMM May 15 '19 at 17:53
  • The first answer there explains the exact same problem, the second one shows how to resolve it. – LogicStuff May 15 '19 at 18:00
  • 1
    I've modified the question a bit, after a bit more of a thorough look at the difference between this question, and the linked topic. – ChrisMM May 15 '19 at 18:00
  • 1
    Try `return this->createEditorHidden( parent );` and make sure that your SFINAE conditions are disjunctive (which is not the case between the 2nd and 3rd overload - typo?). Lastly, `std::enable_if` can be written in much shorter form (the second template parameter does not matter here, keep the default `void`): `std::enable_if::type* = 0` or `= nullptr`. Since C++17, you can also drop `typename` if using `std::enable_if_t`. – LogicStuff May 15 '19 at 18:09
  • Ugh. Never mind, I figured it out. I needed ```bool``` as the type parameter of ```std::enable_if``` not ```QWidget*```. Got it at the same time as you posted that, basically. Just used bool instead, but same idea in the end. – ChrisMM May 15 '19 at 18:09

0 Answers0