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