sfinae: условие enable_if

Я всегда вижу, что enable_if используется только с условием std::is_integral::value.

Есть ли способ использовать в условии вызов функции функции-члена объекта другого класса шаблонов? Функция, о которой я говорю, должна выглядеть так:

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

В настоящее время я не могу его скомпилировать, независимо от того, что я пытаюсь.

Спасибо за помощь мне.

изменить:

что мой вопрос более понятен, больше кода и сообщение об ошибке.

главное окно.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;
}

главное окно.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

форма.ч

#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

форма.cpp

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

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

ошибка:

значение 'Form::staticThis' нельзя использовать в константном выражении с именем типа std::enable_if::staticThis->someFunc(),bool>::type ^

Я не хочу использовать в условии enable_if функцию из std или что-то в этом роде. Я хочу использовать свою собственную функцию. И я не знаю, как заставить его работать. Может быть, поэтому вы подумаете, что код немного занят. Но я думаю, что теперь он должен показать, чего я пытаюсь достичь.

Еще раз спасибо


person Ini    schedule 27.04.2016    source источник
comment
Непонятно, что вы хотите. Как то не работает. Как вы ожидаете, что это сработает?   -  person NathanOliver    schedule 27.04.2016
comment
Я разместил больше кода и объяснил его более подробно   -  person Ini    schedule 28.04.2016


Ответы (1)


Не знаю, что вы ищете, но вот пример sfinae, в котором используются функции-члены:

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

ИЗМЕНИТЬ

После редактирования OP я обновляю ответ минимальным рабочим примером, который показывает, как использовать sfinae так, как он хочет.
Для этого функция-член имеет быть constexpr по крайней мере по понятным причинам.

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

Пример OP далеко не минимальный, и я думаю, что не стоит исправлять его.
Вместо этого приведенного выше достаточно, чтобы объяснить идею решения.

ИЗМЕНИТЬ

Как упоминалось в комментариях, C++11 имеет более строгие ограничения на функции constexpr.
Вместо этого вы можете иметь более сложные операторы в функции constexpr, начиная с C++14.
В качестве примера приведенный ниже код компилируется с использованием -std=c++14. , пока он не компилируется с использованием -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'>();
}
person skypjack    schedule 27.04.2016
comment
Так не получится. По крайней мере, функция должна быть constexpr. Я обновляю ответ минимальным рабочим примером. - person skypjack; 28.04.2016
comment
но constexp работает только с одним оператором возврата. У меня есть if в моей функции - person Ini; 28.04.2016
comment
Если вы передаете компилятору аргумент -std=C++14, вы можете использовать что-то более сложное, чем оператор return. Позвольте мне обновить ответ. - person skypjack; 28.04.2016
comment
спасибо, не могли бы вы дать мне ссылку, где сообщается об изменениях constexp в С++ 14? Я не нашел отчета, в котором задокументировано, что constexp теперь может иметь больше операторов возврата, чем один. Конечно, это работает, но я не нашел информации об этом в Интернете. - person Ini; 29.04.2016
comment
Например, вот то, что вы ищете. - person skypjack; 29.04.2016