Value_type di un parametro del modello contenitore

Nel suo keynote di quest’anno Going Native The Essence of C ++ (vai a 40:30) Bjarne Stroustrup fornisce il seguente esempio di codice:

template vector<Value_type*> find_all(C& cont, V v) { vector<Value_type*> res; for (auto& x : cont) if (x == v) res.push_back(&x) return res; } 

Questa funzione viene utilizzata per trovare tutte le occorrenze di un valore in un contenitore e restituisce i puntatori agli elementi trovati. L’esempio dal video:

 string m{"Mary had a little lamb"}; for (const auto p: find_all(m,'a')) // p is a char* if (*p != 'a') cerr << "string bug!\n"; 

La mia domanda riguarda Value_Type* . C’è qualcosa di simile nella libreria standard? L’ho cercato e non l’ho trovato. Come potrebbe essere implementato, se non è in fase di sviluppo?

Non lo so nello standard, ma non è difficile da implementare:

  template  struct value_type { typedef typename C::value_type type; }; template  struct value_type { typedef T type; }; template  struct value_type { typedef T type; }; 

e ora puoi usare typename value_type::type per accedere al tipo che contiene un container. Se si dispone del proprio contenitore che si desidera utilizzare ma non ha un value_type (e per qualsiasi motivo non è ansible cambiarlo), è ansible anche semplicemente specializzare questa struttura per quel contenitore.

Per evitare il typename ...::type puoi fare:

  template  using Value_Type = typedef value_type::type; 

e ora usi Value_Type ovunque.

MODIFICARE
Come suggerito da stefan nella risposta di soon, puoi farlo più facilmente con std::begin che va bene perché qualsiasi contenitore che usi / crei vorresti essere in grado di chiamare std::begin e std::end in ogni caso:

  template  using Value_Type = typename std::remove_reference< decltype(*std::begin(std::declval< typename std::add_lvalue_reference::type>()))>::type; 

Questo è molto più conciso, anche se è diventato un po ‘denso da leggere. È ancora meglio della prima opzione, questo richiederà un codice di codice più basso per i tipi di container personalizzati.

Value_type è solo un typedef per C::value_type . Per quanto ne so, non esiste un typedef nella libreria standard, ma potresti definirlo tu stesso:

 template  using Value_type = typename T::value_type; template std::vector*> find_all(C& cont, V v) { std::vector*> res; for (auto& x : cont) if (x == v) res.push_back(&x); return res; } int main() { std::vector v{1, 2, 3, 3, 5}; for(const auto x: find_all(v, 3)) { std::cout << *x << std::endl; } } 

Ma, come suggerito da @stefan, questo funzionerà solo con i contenitori standard. Puoi recuperare il tipo sottostante usando la funzione std::begin (che è anche definita per gli array), come è implementata nella risposta di @ GuyGreer