I'm trying to create a thread in c ++, but my code does not compile.
The std::thread
utility is created by providing a functor or a function, the facilitated parameter will be executed in parallel to the main thread.
In your case you are creating a std::thread
on a function. In the case of creating a thread on a function, the programmer is expected to provide a function pointer. Unfortunately it fails you because you have not taken into account (or do not know) that in C ++ there are two families of functions:
Free functions .
In this category of functions, all the functions that are not associated with any object, that is, the functions that can be called by their name without putting an object instance, are examples of free functions:
Free functions have the peculiarity that their name is implicitly convertible to pointer 1 , so if we have a type T
that is pointer to a function that does not return anything and receives a pointer to integer and two integers using T = void(*)(int *, int, int)
we can use T
to create pointers to functions with that signature and we can assign them directly the name of the function:
void klatu(int *, int, int) {}
void barada(int *, int, int) {}
void nikto(int *, int, int) {}
void alakhazam() {}
T p_k = klatu; // Correcto, se convierte implicitamente a puntero
T p_b = barada; // Correcto, se convierte implicitamente a puntero
T p_n = &nikto; // Correcto, puntero a la funcion nikto
T p_a = alakhazam; // Error, alakhazam no es convertible a void(*)(int *, int, int)
As you can see the operator address-of can also be used in free functions although the name of the function is implicitly convertible to a pointer of the type of the function.
To use the pointers as if they were the functions they point to, simply put the name of the pointer and pass the parameters in parentheses:
p_k(nullptr, 0, 0); // llama a klatu
p_b(nullptr, 0, 0); // llama a barada
p_n(nullptr, 0, 0); // llama a nikto
Member functions.
In this category of functions would enter the functions that are associated with an object, that is, the functions that need an object instance to be called, these are examples of member functions:
Member functions require an object instance to be called because inside such functions it is possible to use member variables of the object, if we do not have an associated object. How do we access these member variables? it is for this reason that the member functions have a hidden parameter which is this
and for the same reason to refer to them we must also prefix the type of the object they belong to.
Unlike free functions, the member functions require the operator address-to get a pointer to them, so if we have a type T
that is pointer to a function member of a class Programa
and said function returns nothing while receiving an integer pointer and two integers using T = void(Programa::*)(int *, int, int)
we can use T
to create pointers to functions of that class with that signature if we use the operator &
:
struct Programa
{
void Programa::ordenUnoParelelismo()
{
T f = &Programa::quickSortParalelismo; // Correcto
T g = Programa::quickSortParalelismo; // Error, falta '&'
T h = &quickSortParalelismo; // error C2276, falta el nombre de la clase
T i = quickSortParalelismo; // Error, falta el nombre de la clase y '&'
}
quickSortParalelismo(int *, int, int) {}
};
To use the pointers to member functions as if they were the functions to which they point, you must pass both an object instance and the parameters:
struct S
{
void f(int parametro) { std::cout << valor << ' ' << parametro << '\n'; }
int valor{};
} uno{1}, dos{2};
using T = void(S::*)(int);
// puntero apunta a cualquier funcion de 'S' que devuelva 'void' y reciba 'int'
T puntero = &S::f;
/* Llamamos la funcion apuntada por 'puntero' sobre la instancia
vvv <--- 'uno' pasando como parametro '1' */
(uno.*puntero)(1);
/* Llamamos la funcion apuntada por 'puntero' sobre la instancia
vvv <--- 'dos' pasando como parametro '2' */
(dos.*puntero)(2);
You can see the code of this example working on Wandbox 三 へ (へ ਊ) へ ハ ッ ハ ッ .
Your problem.
You guessed that the first parameter of the constructor of a std::thread
is the function to execute and the following parameters of the constructor will be the parameters of the function:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
But as we have seen in the section of Member functions you need the name of the class so that the compiler understands that you are referring to a member function:
std::thread hilo(&Programa::quickSortParalelismo, this->vectorOriginal, inicio, fin);
// ~~~~~~~~ <-- Requiere el nombre de la clase propietaria de la funcion
But this code also fails, that's because we're working with a member function and will also need an object instance to execute that function:
std::thread hilo(&Programa::quickSortParalelismo, *this, this->vectorOriginal, inicio, fin);
// Requiere una instancia de objeto ---> ~~~~~
1 Similar, but not at all the same, to what happens with the fixes ( int arreglo[10]
) in which the name of the array is the pointer to the first element of that array.