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
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