sfinae: enable_if 条件
sfinae: enable_if condition
我总是只看到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;
错误:
'Form::staticThis' 的值在常量表达式中不可用
类型名 std::enable_if::staticThis->someFunc(),bool>::type
^
我不想在 enable_if 条件下使用来自 std 或其他东西的函数。我想使用我自己的功能。而且我不知道如何让它工作。也许这就是为什么你会认为代码有点忙。但我认为它现在应该显示我正在努力完成的事情。
再次感谢您
不确定您要查找的内容,但这里有一个使用成员函数的 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'>();
}
我总是只看到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;
错误:
'Form::staticThis' 的值在常量表达式中不可用 类型名 std::enable_if::staticThis->someFunc(),bool>::type ^
我不想在 enable_if 条件下使用来自 std 或其他东西的函数。我想使用我自己的功能。而且我不知道如何让它工作。也许这就是为什么你会认为代码有点忙。但我认为它现在应该显示我正在努力完成的事情。
再次感谢您
不确定您要查找的内容,但这里有一个使用成员函数的 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'>();
}