<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Is it possible QMetaObject::invokeMethod with non-copyable argument?]]></title><description><![CDATA[<p dir="auto">I know you can't use signals and slots with non-copyable arguments. One signal can be connected to multiple slots, so it must be possible to copy arguments to every slot. But invokeMethod? I can't see any reason for it to not work. Yet I can't figure it out. Example:<br />
Simple class inheriting <code>QObject</code> :</p>
<pre><code>class Bar : public QObject
{
  Q_OBJECT
public:
  void foo1() { qDebug() &lt;&lt; "foo1"; }
  void foo2(int i) { qDebug() &lt;&lt; "foo2 i" &lt;&lt; i;}
  void foo3(std::unique_ptr&lt;int&gt; i) {qDebug() &lt;&lt; "foo3 s.i:" &lt;&lt; *(i.get()); }
};
</code></pre>
<p dir="auto">Let's create an instance of this class and move it to another thread:</p>
<pre><code>Bar * bar = new Bar();  
QThread barThread;
bar-&gt;moveToThread(&amp;barThread);
barThread.start();
</code></pre>
<p dir="auto">Now, I want to call <code>foo1</code>, <code>foo2</code> and <code>foo3</code> in this new thread. Using <code>QMetaObject::invokeMethod</code> it's easy to call <code>foo1</code> and <code>foo2</code>:</p>
<pre><code>QMetaObject::invokeMethod(bar, &amp;Bar::foo1);

int i2 = 7;
QMetaObject::invokeMethod(bar, [bar, i2](){bar-&gt;foo2(i2);});
</code></pre>
<p dir="auto">But when I try to call <code>foo3</code>, the program doesn't compile:</p>
<pre><code>auto i3 = std::make_unique&lt;int&gt;(3);
QMetaObject::invokeMethod(bar, [bar, i3](){bar-&gt;foo3(i3);});
</code></pre>
<p dir="auto">It's because <code>unique_ptr</code> is not copyable. So I use <code>std::move</code>:</p>
<pre><code>QMetaObject::invokeMethod(bar, [c, i = std::move(i3)](){bar-&gt;foo3(std::move(i));});
</code></pre>
<p dir="auto">Still doesn't compile. Am I doing something wrong or is it just not possible to use <code>QMetaObject::invokeMethod</code> with non-copyable argument?</p>
]]></description><link>https://forum.qt.io/topic/145882/is-it-possible-qmetaobject-invokemethod-with-non-copyable-argument</link><generator>RSS for Node</generator><lastBuildDate>Sat, 07 Nov 2026 14:31:50 GMT</lastBuildDate><atom:link href="https://forum.qt.io/topic/145882.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 19 Jun 2023 16:31:25 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Is it possible QMetaObject::invokeMethod with non-copyable argument? on Mon, 19 Jun 2023 19:55:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/tarae">@<bdi>Tarae</bdi></a> Your example does not show a problem with <code>invokeMethod</code> but with your usage of lambda. Even without <code>invokeMethod</code> this won't work, because you're trying to capture <code>i3</code> by copy and unique_ptr is not copyable:</p>
<pre><code class="language-cpp">auto i3 = std::make_unique&lt;int&gt;(3);
auto lambda  = [bar, i3](){bar-&gt;foo3(i3);} // nope, can't do
</code></pre>
<p dir="auto">You need to move the parameter into a capture variable:</p>
<pre><code class="language-cpp">auto lambda  = [bar, i3cp = std::move(i3)](){bar-&gt;foo3(i3cp);}
</code></pre>
<p dir="auto">but this won't compile either, because your function takes a parameter by value, so there's another copy there. You have to move your parameter again:</p>
<pre><code>auto i3 = std::make_unique&lt;int&gt;(3);
auto lambda  = [bar, i3cp = std::move(i3)](){bar-&gt;foo3(std::move(i3cp));}
</code></pre>
<p dir="auto">but then you have another problem, because lambdas are constant by default i.e. its captures are const too and not movable, so you have to make your lambda mutable:</p>
<pre><code>auto lambda  = [bar, i3cp = std::move(i3)]() mutable { bar-&gt;foo3(std::move(i3cp)); }
</code></pre>
<p dir="auto">This will work. Notice, that this lambda is non-copyable, because it captures a unique_ptr, which itself is non-copyable, yet you can still use that lambda in <code>invokeMethod</code>. That's because <code>invokeMethod</code> will move it if it needs to (e.g. when scheduled on another thread's queue).</p>
<p dir="auto">But all in all moving unique_ptrs around like this is kinda shady. It's hard to keep track of what's where and who holds it. I gave you a solution, but I would advise against using it.</p>
]]></description><link>https://forum.qt.io/post/761979</link><guid isPermaLink="true">https://forum.qt.io/post/761979</guid><dc:creator><![CDATA[Chris Kawa]]></dc:creator><pubDate>Mon, 19 Jun 2023 19:55:34 GMT</pubDate></item><item><title><![CDATA[Reply to Is it possible QMetaObject::invokeMethod with non-copyable argument? on Mon, 19 Jun 2023 20:20:17 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/chris-kawa">@<bdi>Chris-Kawa</bdi></a> Thank you for the explanation and the solution.<br />
But I would argue that using unique_ptr is making it harder to keep track of ownership. The one holding the unique_ptr holds the data, it's simple as that.</p>
]]></description><link>https://forum.qt.io/post/761990</link><guid isPermaLink="true">https://forum.qt.io/post/761990</guid><dc:creator><![CDATA[Tarae]]></dc:creator><pubDate>Mon, 19 Jun 2023 20:20:17 GMT</pubDate></item><item><title><![CDATA[Reply to Is it possible QMetaObject::invokeMethod with non-copyable argument? on Mon, 19 Jun 2023 19:55:34 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/tarae">@<bdi>Tarae</bdi></a> Your example does not show a problem with <code>invokeMethod</code> but with your usage of lambda. Even without <code>invokeMethod</code> this won't work, because you're trying to capture <code>i3</code> by copy and unique_ptr is not copyable:</p>
<pre><code class="language-cpp">auto i3 = std::make_unique&lt;int&gt;(3);
auto lambda  = [bar, i3](){bar-&gt;foo3(i3);} // nope, can't do
</code></pre>
<p dir="auto">You need to move the parameter into a capture variable:</p>
<pre><code class="language-cpp">auto lambda  = [bar, i3cp = std::move(i3)](){bar-&gt;foo3(i3cp);}
</code></pre>
<p dir="auto">but this won't compile either, because your function takes a parameter by value, so there's another copy there. You have to move your parameter again:</p>
<pre><code>auto i3 = std::make_unique&lt;int&gt;(3);
auto lambda  = [bar, i3cp = std::move(i3)](){bar-&gt;foo3(std::move(i3cp));}
</code></pre>
<p dir="auto">but then you have another problem, because lambdas are constant by default i.e. its captures are const too and not movable, so you have to make your lambda mutable:</p>
<pre><code>auto lambda  = [bar, i3cp = std::move(i3)]() mutable { bar-&gt;foo3(std::move(i3cp)); }
</code></pre>
<p dir="auto">This will work. Notice, that this lambda is non-copyable, because it captures a unique_ptr, which itself is non-copyable, yet you can still use that lambda in <code>invokeMethod</code>. That's because <code>invokeMethod</code> will move it if it needs to (e.g. when scheduled on another thread's queue).</p>
<p dir="auto">But all in all moving unique_ptrs around like this is kinda shady. It's hard to keep track of what's where and who holds it. I gave you a solution, but I would advise against using it.</p>
]]></description><link>https://forum.qt.io/post/761979</link><guid isPermaLink="true">https://forum.qt.io/post/761979</guid><dc:creator><![CDATA[Chris Kawa]]></dc:creator><pubDate>Mon, 19 Jun 2023 19:55:34 GMT</pubDate></item><item><title><![CDATA[Reply to Is it possible QMetaObject::invokeMethod with non-copyable argument? on Mon, 19 Jun 2023 20:09:59 GMT]]></title><description><![CDATA[<p dir="auto">Hi,</p>
<p dir="auto"><s>AFAIK, I don't think you can move around unique_ptr with invokeMethod.</s><br />
See <a class="plugin-mentions-user plugin-mentions-a" href="/user/chris-kawa">@<bdi>Chris-Kawa</bdi></a>'s excellent answer.</p>
<p dir="auto">That noted, all your examples with unique_ptr looks like you are trying to reproduce with a lambda what invokeMethod already does.</p>
]]></description><link>https://forum.qt.io/post/761969</link><guid isPermaLink="true">https://forum.qt.io/post/761969</guid><dc:creator><![CDATA[SGaist]]></dc:creator><pubDate>Mon, 19 Jun 2023 20:09:59 GMT</pubDate></item></channel></rss>