-1

I just can't get QtConcurrent::run working with an overloaded static method:

class Foobar {
public:
    static ResType foo(const cv::Mat& data, const QStringList& names, int clusters = 5);
    static ResType foo(const cv::Mat& data, const cv::TermCriteria& tc, const QStringList& names, const QStringList& otherNames, int clusters, int covType = 2);
}

QtConcurrent::run(
    static_cast<ResType (*)(const cv::Mat&, const cv::TermCriteria&,
        const QStringList&, const QStringList&, int, int)>(&Foobar::foo),
        sampleData, tc, mDimNames, mGmmNames, mClusterN, mCovType);

I get:

error: no matching function for call to ‘run(ResType (*)(const cv::Mat&, const cv::TermCriteria&, const QStringList&, const QStringList&, int, int), cv::Mat&, cv::TermCriteria&, QStringList&, QStringList&, int&, int&)’ sampleData, tc, mDimNames, mGmmNames, mClusterN, mCovType);

Note the ref (&) in the error message for the integer parameters. This baffles me....

Types of params:

cv::Mat sampleData, cv::TermCriteria tc, QStringList mDimNames, QStringList mGmmNames, int mClusterN, int mCovType

I thought the static_cast would help with distinguishing the overloads. The only difference I can see is, that the params are partly not const. But you can take a const ref of a Value type param, so why would that matter...

Benjamin Maurer
  • 3,602
  • 5
  • 28
  • 49
  • The code in your question is a mix of the original and the one you edited for posting, as much as I can guess. (`DkGmm` or `Foobar`? `Foobar` is in namespace `bla`?) Making it consistent can help understanding what's going on. – Yehezkel B. Sep 15 '16 at 23:01
  • Sorry, I fixed it – Benjamin Maurer Sep 16 '16 at 07:20

2 Answers2

2

The answer is that static member function type is a regular function, not a member function, because it doesn't have the implicit this, so removing the Foobar:: part before * should since the compilation issue.

Edit:

After the question edition and the answer added by OP, I want to mention that std::bind is not a great solution. It's very error-prone, especially around the "get by ref" which easily becomes a copy if you are not very careful. The better solution is to use a lambda instead. E.g:

auto future = QtConcurrent::run([&]{
    DkGmm::fromData(sampleData, tc, mDimNames, mGmmNames, mClusterN, mCovType); });

(In the actual code, I'd probably capture each of the arguments explicitly, as I think that using the default capturing is Bad Practice™.)

Yehezkel B.
  • 1,140
  • 6
  • 10
  • That is correct, I have already fixed that. I still get an error. I will update the question. Also, I've just solved my problem by using std::bind. I'm already writing it up. – Benjamin Maurer Sep 16 '16 at 11:04
  • Could you specify why it is not a great solution? Concerning "Error prone", are you refering to the signature in the cast or is there anything else to watch out for? – Benjamin Maurer Sep 19 '16 at 07:52
  • Quoting myself: "especially around the "get by ref" which easily becomes a copy if you are not very careful". I'm pretty sure you get copies there because you didn't use `std::cref()` for each of the arguments passed to the `bind`. If you don't believe me, take it from Scott Meyers (Effective Modern C++, Item 34: Prefer lambdas to std::bind). – Yehezkel B. Sep 19 '16 at 18:40
0

std::bind to the rescue. For some reason, it can figure out the right type:

#include <functional>

void test() {
    auto fn = std::bind(
        static_cast<DkGmm (*)(const cv::Mat&, const cv::TermCriteria&, const QStringList&, const QStringList&, int, int)>(&DkGmm::fromData),
        sampleData, tc, mDimNames, mGmmNames, mClusterN, mCovType);

    auto future = QtConcurrent::run(fn);
// ...code...
}
Benjamin Maurer
  • 3,602
  • 5
  • 28
  • 49