La proposta di operatori funzionali trasparenti è lì come un modo per avere funtori generalizzati che si trovano in <functional>
. Personalmente ritengo che la proposta stessa abbia un ottimo esempio che aiuterebbe a illustrarne la necessità. Comunque andrò avanti e cercherò di spiegarlo.
Supponiamo di avere una funzione, una funzione mente molto di base si:
template<typename T, typename U>
auto less_than(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)) {
return std::forward<T>(t) < std::forward<U>(u);
}
Tuttavia si desidera utilizzare questa funzione generalizzata nell'intestazione <algorithm>
. Hai due opzioni, per renderlo un funtore struct:
struct MyLessThanFunctor {
template<typename T, typename U>
auto operator()(T&& t, U&& u) -> decltype(std::forward<T>(t) < std::forward<U>(u)){
return std::forward<T>(t) < std::forward<U>(u);
}
};
O in C++ 14, per fare una lambda polimorfico:
[](auto&& t, auto&& u) -> decltype(auto) {
return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u);
}
Entrambi sono molto verboso quando viene utilizzato in un algoritmo in questo modo :
int main() {
std::vector<int> v = {112,12,1281271,1919101,29181,412,1 };
std::sort(std::begin(v), std::end(v), MyLessThanFunctor()); // one
std::sort(std::begin(v), std::end(v), [](auto&& t, auto&& u) -> decltype(auto) {
return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u);
});
}
questa proposta mira a rendere più compatto e generalizzata facendo questo invece:
std::sort(std::begin(v), std::end(v), std::less<>());
Ciò consente un inoltro perfetto e risolve i problemi con il troncamento oi problemi derivanti dalla modifica del contenitore ma non il tipo sottostante nominato dal contenitore come indicato dalla carta.
Supponiamo di avere un funtore non generalizzata:
struct Functor {
bool operator()(uint32_t a, uint32_t b) {
return a < b;
}
};
e si utilizza con il vostro std::vector<uint32_t>
e funziona tutto bene, ma dimenticare il tuo functor non essere generalizzata e utilizzarlo con il vostro std::vector<uint64_t>
. Riesci a vedere il problema che è sorto? Gli elementi verranno troncati prima di essere confrontati, il che probabilmente non è ciò che l'utente desiderava. I funtori generalizzati risolvono questo problema prima che si presentino.
Se è lo stesso, consente di sostituire 'bool less :: operator() (int const e lhs, int const & rhs) const {return lhs :: operator() (LHS && lhs, RHS && rhs) const-> decltype (std :: forward (lhs) (rhs)) {return std :: forward (lhs) (rhs); } ', una perfetta chiamata" trasparente "di inoltro a' <'. –
Yakk
N3421 è la stessa cosa: è stato votato in C++ 14 senza modifiche in quella riunione, ed è quello che ho implementato nel 2013 Anteprima. Ho pensato che la sezione II, "Motivation And Scope", spiegasse chiaramente il problema e la soluzione, e ho pensato che l'esempio nella sezione VIII "Implementazione" ne dimostrasse l'uso. Di cosa sei confuso? –
La pagina "Novità per Visual C++" non menziona la proposta N3421, quindi ho pensato di chiedere qui. Sono chiaro su di esso ora. Grazie per averlo aggiunto. – GravityWell