1
votes

I always only see enable_if is used with the condition std::is_integral::value.

Is there a way to use in the condition a function-call of a memberfunction of an object of another templateclass? The function I'm talking about should look like this:

bool someFunc()
{
    if (QString(T::staticMetaObject.className()) == QString("Form")) {
        return true;
    }
    return false;   
}

Currently I cannot get it compiled no matter what I try.

Thank you for helping me.

edit:

that my question is more clear more code and an error msg.

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
#include <type_traits>
#include <QDebug>

template <class T>
typename std::enable_if<Form<MainWindow>::staticThis->someFunc(),bool>::type
  is_smth (T* obj) { return true; }

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    form = new Form<MainWindow>;

    qDebug() << is_smth(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "form.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    Form<MainWindow>* form;

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

form.h

#ifndef FORM_H
#define FORM_H
#include <QObject>

class FormBase : public QObject
{
    Q_OBJECT
};

template <class T>
class Form : public FormBase
{
public:
    Form() {}

    static Form* staticThis;

    bool someFunc()
    {
        if (QString(T::staticMetaObject.className()) == QString(Form::staticMetaObject.className())) {
            return true;
        }
        return false;
    }
};

#endif // FORM_H

form.cpp

#include "form.h"
#include "mainwindow.h"

Form<MainWindow>* Form::staticThis = NULL;

error:

the value of 'Form::staticThis' is not usable in a constant expression typename std::enable_if::staticThis->someFunc(),bool>::type ^

I'm do not want to use in condition of enable_if a function from std or something. I want to use my own function. And i don't know how to get it work. Maybe thats why you will think the code is a little bit busy. But i think it should show now what I'm trying to accomplish.

Thank you again

1
Its unclear what you want. How is it not working. How do you expect it to work?NathanOliver
I posted more code and explained it in more detailIni

1 Answers

0
votes

Not sure about what you are looking for, but here is an example of sfinae that uses member functions:

#include<type_traits>

template<typename T>
std::enable_if_t<std::is_member_function_pointer<T>::value>
foo() { }

struct S {
    void bar() { }
    int i;
};

int main() {
    // compiles, for it is a member function
    foo<decltype(&S::bar)>();
    // does not compile, for it is not a member function
    //foo<decltype(&S::i)>();
}

EDIT

After the edit of the OP, I'm updating the answer with a minimal, working example that shows how to use sfinae the way he wants.
In order to do that, the member function has to be constexpr at least for obvious reasons.

#include<type_traits>

struct S {
    static constexpr bool bar(bool b) { return b; }
};

template<bool b>
std::enable_if_t<S::bar(b)>
foo() { }

int main() {
    foo<true>();
    // fails to compile because of sfinae
    // foo<false>();
}

The OP's example is far from being a minimal one and I guess it doesn't worth to fix it.
Instead, the one above is enough to explain the idea behind the solution.

EDIT

As mentioned in the comments, C++11 has stricter limitations on constexpr functions.
Instead you can have more complex statements in a constexpr function since C++14.
As an example, the code below compiles using -std=c++14, whilst it doesn't compile using -std=c++11:

#include<type_traits>

struct T {
    constexpr T(char c): ch{c} { }
    char ch;
};

struct S {
    static constexpr bool bar(T&& t) {
        if(t.ch == 'y') {
            return static_cast<unsigned int>(t.ch) % 2 == 0;
        } else {
            return true;
        }
    }
};

template<char c>
std::enable_if_t<S::bar(T{c})>
foo() { }

int main() {
    foo<'x'>();
    // fails to compile because of sfinae
    // foo<'y'>();
}