Error creating thread in c ++

2

I'm trying to create a thread in c ++, but my code does not compile.

void Programa::ordenUnoParelelismo()
{
    std::cout << "<<-- ALGORITMO UNO PARALELISMO -->>" << std::endl;
    int hilos = intInput("Ingrese numero de hilos: ");
    std::vector<std::thread> vt; //Contiene los hilos
    bool posible = this->cantidad / hilos >= 2;
    while(!posible) {
        std::cout << "No es posible ordenar el vector con tantos hilos." << std::endl;
        hilos = intInput("Ingrese numero de hilos: ");
    }
    std::cout << "Hilos: " << hilos << std::endl;
    //Quicksort Paralelismo
    int separacion = ceil((double)this->cantidad / hilos);
    int inicio = 0;
    int fin = (inicio + separacion) - 1;
    for (int i = 0; i < hilos; i++) {
        if (fin >= this->cantidad) {
            fin = this->cantidad-1;
        }
        std::thread hilo(&quickSortParalelismo, this->vectorOriginal, inicio, fin);
        vt.push_back(hilo);
        inicio = fin + 1;
        fin = (inicio + separacion) - 1;
    }
}

void Programa::quickSortParalelismo(int * arr, int inicio, int fin)
{
    int pivote = arr[fin];
}

This is the error that comes out:

error C2276: '&': operación no válida de la expresión de función miembro enlazada

And it's in this line:

std::thread hilo(&quickSortParalelismo, this->vectorOriginal, inicio, fin);

Please, just answer my question about why the error appears. If the QuickSort algorithm is bad, it's my job to solve it. Thank you very much.

    
asked by JCAguilera 08.12.2017 в 13:55
source

3 answers

4

You need to pass the pointer this as the first parameter of your method, we are talking about non-static methods, then consider this example:

class test
{
    public:
        int MyMember;

        void MyMethodA(int a);  
        void InitThread();  
};

void test::MyMethodA(int a)
{
    std::cout << "V: " << a << std::endl;
}

void test::InitThread()
{
    std::thread tx(&test::MyMethodA, this, this->MyMember);
    tx.join();
}

int main()
{
   test ins;
   ins.InitThread();

   return 0;
}

The pointer this is used in each of the methods of a class for the reference of the current instance ...

    
answered by 08.12.2017 в 15:12
3

Alternatively to the response from @nikomaster , and because of what you see in your code, you can declare your function quickSortParalelismo( ) as static .

This solution is only valid without you do not use any non-static member-variable in the function code.

class Programa {
public:
  static void quickSortParalelismo( int *, int, int );
  ...
};
    
answered by 08.12.2017 в 15:36
3
  

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.

    
answered by 13.12.2017 в 12:01