Propozycja przezroczystych operatorów jest dostępna jako sposób na uogólnione funktory, które znajdują się w <functional>
. Osobiście uważam, że sama propozycja ma bardzo dobry przykład, który pomógłby zilustrować jej potrzebę. Niemniej jednak postaram się to wyjaśnić.
Załóżmy, że masz funkcję, bardzo prosty umysł funkcyjny Ciebie:
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);
}
jednak chcesz skorzystać z tej uogólnione funkcji w nagłówku <algorithm>
. Masz dwie możliwości, aby to funktor 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);
}
};
Albo w C++ 14, aby polimorficzny lambda:
[](auto&& t, auto&& u) -> decltype(auto) {
return std::forward<decltype(t)>(t) < std::forward<decltype(u)>(u);
}
Oba są bardzo gadatliwe, gdy wykorzystywane w algorytmie tak jak :
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);
});
}
propozycja ta ma na celu uczynienie go bardziej zwarty i uogólnione w ten sposób zamiast:
std::sort(std::begin(v), std::end(v), std::less<>());
Zapewnia to doskonałe przekazywanie i rozwiązuje problemy związane ze skróceniem lub problemami wynikającymi ze zmiany kontenera, ale nie z podstawowym typem wyznaczonym przez kontener, jak wspomniano w dokumencie.
Załóżmy, że masz non-uogólnioną funktor:
struct Functor {
bool operator()(uint32_t a, uint32_t b) {
return a < b;
}
};
i używasz go z std::vector<uint32_t>
i działa wszystko w porządku, ale można zapomnieć o swojej funktora nie są uogólnione i używać go z std::vector<uint64_t>
. Czy widzisz problem, który się pojawił? Elementy zostaną obcięte przed porównaniem, co prawdopodobnie nie jest tym, czego chciał użytkownik. Uogólnione funktory rozwiązują ten problem, zanim się pojawią.
Jeśli to jest to samo, pozwala zastąpić 'bool less :: operator() (int const & lhs, int const & rhs) const {return lhs :: operator() (LHS && lhs, RHS && rhs) const-> decltype (std :: forward (lhs) (rhs)) {return std :: forward (lhs) (rhs); } ', idealne przekazywanie" przezroczystego "wywołania' <'. –
Yakk
N3421 to to samo - zostało ono poddane pod głosowanie w C++ 14 bez modyfikacji na tym spotkaniu, a to zaimplementowałem w 2013 Preview. Pomyślałem, że sekcja II, "Motywacja i zakres", jasno wyjaśniła problem i rozwiązanie, i pomyślałem, że przykład w sekcji VIII "Wdrożenie" wykazał jego zastosowanie. Co cię myli? –
Strona "Co nowego w Visual C++" nie zawiera propozycji N3421, więc pomyślałem, że o to tutaj zapytam. Teraz jestem jasny. Dziękujemy za dodanie. – GravityWell