6

I try to call a member function of an object using a thread.

If the function doesn't have a variadic template (Args ... args), no problem, it works:

Consider the two classes:

GeneticEngine

template <class T>
class GeneticEngine
{
    template <typename ... Args>
    T* run_while(bool (*f)(const T&),const int size_enf,Args& ... args)
    {
         std::thread(&GeneticThread<T>::func,islands[0],f,size_enf);
         /* Some code */
         return /* ... */
    }
    private:
        GeneticThread<T>** islands;


}

GeneticThread

template <class T>
class GeneticThread
{
    void func(bool (*f)(const T&),const int size_enf)
    {
        /* Some code */
    };
}

With this, it's OK.


Now, I add a variadic template to the same functions:

GeneticEngine

template <class T>
class GeneticEngine
{
    template <typename ... Args>
    T* run_while(bool (*f)(const T&,Args& ...),const int size_enf,Args& ... args)
    {
       std::thread(&GeneticThread<T>::func,islands[0],f,size_enf,args ...);
       /* Other code ... */
    }
    private:
        GeneticThread<T>** islands;
}

GeneticThread

template <class T>
class GeneticThread
{
    template <typename ... Args>
    void func(bool (*f)(const T&,Args& ...), const int size_enf, Args& ... args)
    {
       /* Code ... */
    };
 }

With this code, GCC doesn't compile: (sorry for this error message)

g++ main.cpp GeneticEngine.hpp GeneticThread.hpp Individu.hpp GeneticThread.o -g -std=c++0x    -o main.exe
In file included from main.cpp:2:0:
GeneticEngine.hpp: In instantiation of ‘T* GeneticEngine<T>::run_while(bool (*)(const T&, Args& ...), int, Args& ...) [with Args = {}; T = Individu]’:
main.cpp:24:78:   required from here
GeneticEngine.hpp:20:13: erreur: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, GeneticThread<Individu>*&, bool (*&)(const Individu&), const int&)’
GeneticEngine.hpp:20:13: note: candidates are:
In file included from GeneticThread.hpp:14:0,
             from GeneticEngine.hpp:4,
             from main.cpp:2:
/usr/include/c++/4.7/thread:131:7: note: template<class _Callable, class ... _Args> std::thread::thread(_Callable&&, _Args&& ...)
/usr/include/c++/4.7/thread:131:7: note:   template argument deduction/substitution failed:
In file included from main.cpp:2:0:
GeneticEngine.hpp:20:13: note:   couldn't deduce template parameter ‘_Callable’
In file included from GeneticThread.hpp:14:0,
             from GeneticEngine.hpp:4,
             from main.cpp:2:
/usr/include/c++/4.7/thread:126:5: note: std::thread::thread(std::thread&&)
/usr/include/c++/4.7/thread:126:5: note:   candidate expects 1 argument, 4 provided
/usr/include/c++/4.7/thread:122:5: note: std::thread::thread()
/usr/include/c++/4.7/thread:122:5: note:   candidate expects 0 arguments, 4 provided

I really do not understand why this difference makes this error. And I can not fix it.


In both the main.cpp is like that:

/* Individu is another class */

int pop_size = 1000;
int pop_child = pop_size*0.75;

GeneticEngine<Individu> engine(/*args to constructor*/);

bool (*stop)(const Individu&) = [](const Individu& best){
    return false;
};
Individu* best = engine.run_while(stop,pop_child);

I use : «gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1) »


I tried:

std::thread(&GeneticThread<T>::func<Args...>, islands[0], f, size_enf, args ...);

Now I have another error:

GeneticEngine.hpp: In member function ‘T* GeneticEngine<T>::run_while(bool (*)(const T&, Args& ...), int, Args& ...)’:
GeneticEngine.hpp:20:53: erreur: expansion pattern ‘((& GeneticThread<T>::func) < <expression error>)’ contains no argument packs
GeneticEngine.hpp:20:24: erreur: expected primary-expression before ‘(’ token
GeneticEngine.hpp:20:53: erreur: expected primary-expression before ‘...’ token



template <typename ... Args>
T* run_while(bool (*f)(const T&,Args& ...), const int size_enf, Args& ... args)
{

   void (GeneticThread<T>::*ptm)(bool (*)(T const&, Args&...), int, Args&...) = &GeneticThread<T>::func;
   std::thread(ptm, islands[0], f, size_enf, args ...);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Krozark
  • 862
  • 9
  • 27
  • Try `&GenericThread::func`. – Luc Danton May 06 '13 at 22:40
  • 1
    It looks like GCC is having trouble with the pattern expansion. Can you try either `auto ptm = &GenericThread::func;` or `void (GenericThread::*ptm)(bool (*)(T const&, Args&...), int, Args&...) = &GenericThread::func;` separately, then passing `ptm` to the `std::thread` constructor? – Luc Danton May 06 '13 at 22:52
  • As succinctly as possible, function templates are not functions, and there's no such thing as taking the address of a function template. Instead, in this situation the name of the function template behaves as if it were the name of an overload set of functions. See [this](http://stackoverflow.com/questions/2942426/how-to-specify-a-pointer-to-an-overloaded-function) when it comes to taking the address of overloaded functions. (That GCC cannot take the address of the function template specialization should be a bug however.) – Luc Danton May 06 '13 at 23:02
  • Thank you, I understand better now. – Krozark May 06 '13 at 23:08

1 Answers1

4

Try:

std::thread(&GeneticThread<T>::func<Args...>, islands...

func is now a template function. You have to specify its template parameters to be able to take its address.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jmihalicza
  • 2,083
  • 12
  • 20