6

I'm having trouble creating a QVariant with a custom type. Here is a small example that shows what I want to achieve:

main.cpp:

#include "MyClass.h"

int main() {
  MyClass some_object;
  QVariant variant(some_object);
  return 0;
}

include/MyClass.h:

#pragma once

#include <QtCore>

class MyClass {
public:
  MyClass() : _my_member(0.0) {}

  MyClass(const MyClass &other) { _my_member = other._my_member; }

  ~MyClass() {}

  MyClass& operator=(MyClass& other)
  {
    swap(*this, other);
    return *this;
  }

  MyClass(MyClass&& other) : MyClass()
  {
    swap(*this, other);
  }

  friend void swap(MyClass& first, MyClass& second)
  {
    using std::swap;
    swap(first._my_member, second._my_member);
  }

private:
  float _my_member;
};
Q_DECLARE_METATYPE(MyClass);

The build fails with the following error:

error: no matching function for call to ‘QVariant::QVariant(MyClass&)’
  QVariant variant(some_object);
                              ^

How can I solve this error?

rocambille
  • 15,398
  • 12
  • 50
  • 68
  • 3
    have you read this? http://doc.qt.io/qt-5/custom-types.html it seems more a problem that your type is not really registered as one of qt's meta types – Hayt Sep 16 '16 at 07:44
  • Unrelated to CMake. Please edit the tag out. – usr1234567 Sep 16 '16 at 07:58
  • @Hayt Yes, I have read this site and followed its instructions. – wonkydonkey Sep 16 '16 at 08:00
  • @usr1234567 Sorry, I fail to see how this is not related to CMake. Edit: You are right. It was indeed not related to CMake. – wonkydonkey Sep 16 '16 at 08:02
  • 1
    @user2925177 this is a compilation problem. This is more a Qt usage problem and not cmake. In the example linked in the article the Variant value is set with `QVariant stored; stored.setValue(message);` Have you tried this? – Hayt Sep 16 '16 at 08:03
  • The assignment operator should take const MyClass& other as argument. please correct this error as a first step because this is a fundamental error. – user2672165 Sep 16 '16 at 08:16
  • @user2672165 Personally I think you are right, but I was following the copy-and-swap idiom as explained in [this question](http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom). Note that the use of the `swap` function within the assignment operator invalidates the const correctness, so it is impossible to use `const` there. – wonkydonkey Sep 16 '16 at 08:30

2 Answers2

8

You're calling QVariant's constructor with an instance of MyClass: there is no such constructor in QVariant. What you're looking for is QVariant::fromValue:

#include "MyClass.h"

int main() {
  MyClass some_object;
  QVariant variant = QVariant::fromValue(some_object);
  return 0;
}

Alternatively, you can use QVariant::setValue:

#include "MyClass.h"

int main() {
  MyClass some_object;
  QVariant variant;
  variant.setValue(some_object);
  return 0;
}

Note:

To retrieve the value from QVariant, you will have to use the template method QVariant::value, optionally with QVariant::canConvert:

if (variant.canConvert<MyClass>())
    MyClass retrieve_object = variant.value<MyClass>();

Note2:

Looks like you tried to implement copy-and-swap idiom. Your operator= should be:

MyClass& operator=(MyClass other)
{
  swap(*this, other);
  return *this;
}

Instead of:

MyClass& operator=(MyClass& other)
{
  swap(*this, other);
  return *this;
}

If you perform a swap with a reference, other will be modified, and I doubt you want it.

rocambille
  • 15,398
  • 12
  • 50
  • 68
6

To make QVariant object from your class use fromValue method of QVariant:

QVariant variant = QVariant::fromValue(some_object);

You have error, because there is no such constructor in QVariant with parameter of type MyClass&.

Kirill Chernikov
  • 1,387
  • 8
  • 21