I have the following code that does not compile with Qt 6.7.2 on Debian :
#include <QCoreApplication>
#include <iostream>
#include <variant>
class Foo : public QObject
{
Q_OBJECT
};
class Bar : public QObject
{
Q_OBJECT
};
struct Vis
{
void operator()(const Foo &f)
{
std::cout << "foo visitor" << std::endl;
}
void operator()(const Bar &b)
{
std::cout << "bar visitor" << std::endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::variant<Bar, Foo> v;
Foo f;
Bar b;
v = b;
std::visit(Vis{}, v);
v = f;
std::visit(Vis{}, v);
return a.exec();
}
#include "main.moc"
The error is :
error: no match for ‘operator=’ (operand types are ‘std::variant<Bar, Foo>’ and ‘Bar’)
v = b;
As a workaround it seems ok to use raw pointers to QObject
's instead :
struct Vis
{
void operator()(const Foo *f)
{
std::cout << "foo visitor" << std::endl;
}
void operator()(const Bar *b)
{
std::cout << "bar visitor" << std::endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
std::variant<Bar *, Foo *> v;
Foo *f;
Bar *b;
v = b;
std::visit(Vis{}, v);
v = f;
std::visit(Vis{}, v);
return a.exec();
}
Am i missing something to store a QObject
derived class inside a std::variant
?
QObject
has no assignment, hence neither Foo
nor Bar
have an assignment operator. For the reasons I refer you to https://doc.qt.io/qt-5/object.html#identity-vs-value. This would fail with similar eror for the same reason:
Foo f;
Foo g;
f = g;
As Foo
and Bar
already share a common base you can make use of polymorphism. Rather than using std::visit
use virtual functions:
struct foobarable {
virtual ~foobarable() {}
virtual void foobar() = 0;
};
class Foo : public QObject,foobarable
{
Q_OBJECT
void foobar() override { std::cout << "foo" << std::endl; }
};
class Bar : public QObject,foobarable
{
Q_OBJECT
void foobar() override { std::cout << "bar" << std::endl; }
};
As mentioned in a comment, if you really want to use std::variant<Foo,Bar>
a workaround would be to use emplace
to construct the instance in place:
std::variant<Bar, Foo> v;
v.emplace<Bar>();
std::visit(Vis{}, v);
v.emplace<Foo>();
std::visit(Vis{}, v);