sfinae:enable_if condition

时间:2016-04-27 19:53:17

标签: c++ sfinae enable-if

我总是只看到enable_if与条件std :: is_integral :: value一起使用。

有没有办法在条件中使用另一个模板类的对象的成员函数的函数调用?我所谈论的功能应如下所示:

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

目前无论我尝试什么,我都无法编译。

感谢您帮助我。

修改

我的问题是更清楚更多代码和错误信息。

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;

错误:

&#39; Form :: staticThis&#39;的值不能用于常量表达式  typename std :: enable_if :: staticThis-&gt; someFunc(),bool&gt; :: type                                                                 ^

我不想在st_或其他东西的enable_if函数的条件下使用。我想用自己的功能。而且我不知道如何让它发挥作用。也许这就是为什么你会认为代码有点繁忙。但我认为它现在应该显示我想要完成的事情。

再次感谢您

1 个答案:

答案 0 :(得分:0)

不确定您要查找的内容,但以下是使用成员函数的 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函数有更严格的限制 相反,自从C ++ 14以来,你可以在constexpr函数中使用更复杂的语句 例如,下面的代码使用-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'>();
}