2016-02-28 16 views
9

Ho letto molti post su modelli variadic e std :: bind ma penso di non capire ancora come lavorano insieme. Penso che i miei concetti siano un po 'confusi quando si tratta di usare modelli variadici, per quale std :: bind viene usato e come si legano tutti insieme.Un po 'confuso riguardo a std :: ref() e std :: bind() con modelli variadici

Nel seguente codice my lambda utilizza l'operatore punto con oggetti di tipo TestClass ma anche quando passo in oggetti di tipo std :: ref funzionano ancora. Come è esattamente? Come avviene la conversione implicita?

#include <iostream> 
using std::cout; 
using std::endl; 
#include <functional> 
#include <utility> 
using std::forward; 

class TestClass { 
public: 
    TestClass(const TestClass& other) { 
     this->integer = other.integer; 
     cout << "Copy constructed" << endl; 
    } 
    TestClass() : integer(0) { 
     cout << "Default constructed" << endl; 
    } 
    TestClass(TestClass&& other) { 
     cout << "Move constructed" << endl; 
     this->integer = other.integer; 
    } 

    int integer; 
}; 

template <typename FunctionType, typename ...Args> 
void my_function(FunctionType function, Args&&... args) { 
    cout << "in function" << endl; 
    auto bound_function = std::bind(function, args...); 
    bound_function(); 
} 

int main() { 

    auto my_lambda = [](const auto& one, const auto& two) { 
     cout << one.integer << two.integer << endl; 
    }; 

    TestClass test1; 
    TestClass test2; 
    my_function(my_lambda, std::ref(test1), std::ref(test2)); 

    return 0; 
} 

Più specificamente, passo a due istanze di un reference_wrapper con i due oggetti TestClasstest1 e test2, ma quando li passo al lambda all'operatore . funziona magicamente. Mi aspetterei che avete utilizzare la funzione ::get() nella reference_wrapper per fare questo lavoro, ma la chiamata al membro di dati .integer funziona ..

+0

* "Come avviene la conversione implicita?" * - conversione implicita tra quali tipi? – soon

+0

aggiornerò la mia domanda per essere più chiara. Mi dispiace per quello – Curious

+0

@soon There! Questo rende la mia domanda più chiara? – Curious

risposta

5

Lo Scartare di riferimento viene eseguita dal risultato di std::bind():

Se l'argomento è di tipo std::reference_wrapper<T> (ad esempio, std::ref o std::cref è stato utilizzato nella chiamata iniziale a bind), quindi il riferimento T& memorizzato nell'argomento associato viene passato all'oggetto invocabile.

I corrispondenti standard possono essere trovati in N4140 bozza, [func.bind.bind]/10.

+0

Wow! È così magico. Potresti anche suggerire qualcosa da cui potrei imparare di più su questi template std :: bind e variadic? Perché attualmente sembrano essere magici per me e non posso davvero programmare quando le cose sembrano magiche ... – Curious

+0

@Curious [The Definitive C++ Book Guide e List] (http://stackoverflow.com/q/388242/3959454) –

+2

@Curious: vale la pena menzionare che probabilmente è necessario studiare separatamente i modelli di binding e variadic. Non hanno interazioni inusuali, legano gli atti esattamente con o senza variadics, e le variadie agiscono esattamente allo stesso modo con o senza legame. In quanto tale, è meno di un sovraccarico di testa studiarli separatamente. –

0

È importante notare che con std::bind;

Gli argomenti bind vengono copiati o spostati, e non sono mai passati per riferimento meno avvolto in std::ref o std::cref.

Il "visto per riferimento" viene raggiunto perché std::ref fornisce un risultato di std::reference_wrapper che è un tipo di valore che "avvolge" il riferimento fornito.

std::reference_wrapper è un modello di classe che include un riferimento in un oggetto copiabile e assegnabile. Viene spesso utilizzato come meccanismo per memorizzare riferimenti all'interno di contenitori standard (come std::vector) che normalmente non possono contenere riferimenti.

A titolo di esempio di ciò unwrapping bind s' del riferimento fa (senza bind);

#include <iostream> 
#include <utility> 
#include <functional> 

int main() 
{ 
    using namespace std; 
    int a = 1; 
    auto b = std::ref(a); 
    int& c = b; 
    cout << a << " " << b << " " << c << " " << endl; // prints 1 1 1 
    c = 2; 
    cout << a << " " << b << " " << c << " " << endl; // prints 2 2 2 
} 

Demo code.

Problemi correlati