【问题标题】:sfinae: enable_if conditionsfinae: enable_if 条件
【发布时间】:2016-04-30 18:08:29
【问题描述】:

我总是只看到 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

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;

错误:

'Form::staticThis' 的值不能用于常量表达式 类型名 std::enable_if::staticThis->someFunc(),bool>::type ^

我不想在 enable_if 条件下使用 std 或其他东西的函数。我想使用我自己的功能。而且我不知道如何让它工作。也许这就是为什么你会认为代码有点忙。但我认为它现在应该显示我正在努力实现的目标。

再次感谢您

【问题讨论】:

  • 不清楚你想要什么。怎么不行。您希望它如何工作?
  • 我发布了更多代码并更详细地解释了它

标签: c++ sfinae enable-if


【解决方案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 的示例远非最小的示例,我想它不值得修复。
相反,上面的一个足以解释解决方案背后的想法。

编辑

如 cmets 中所述,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'>();
}

【讨论】:

  • 这样就不行了。至少,函数必须是constexpr 之一。我正在用一个最小的工作示例更新答案。
  • 但 constexp 仅适用于一个返回语句。我的函数中有一个 if
  • 如果您将-std=C++14 参数传递给编译器,您可以使用比return 语句更复杂的东西。让我更新答案。
  • 谢谢,你能给我一个链接到哪里报告 C++14 中 constexp 的变化吗?我没有找到一份报告,其中记录了 constexp 现在可以拥有比一个更多的返回语句。当然可以,但我在互联网上没有找到相关信息。
  • 例如,here 就是您要查找的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 2012-08-23
  • 2021-02-18
  • 1970-01-01
  • 2017-03-29
相关资源
最近更新 更多