Czy istnieje sposób napisania funkcji w C++, która akceptuje zarówno argumenty lvalue, jak i rvalue, bez tworzenia szablonu?Funkcja akceptująca oba argumenty: lvalue i rvalue
Załóżmy na przykład, że napisałem funkcję print_stream
, która czyta z istream
i drukuje dane, które zostały odczytane na ekranie lub coś podobnego.
Myślę, że to rozsądne, aby zadzwonić print_stream
takiego:
fstream file{"filename"};
print_stream(file);
jak również tak:
print_stream(fstream{"filename"});
Ale jak mogę zadeklarować print_stream
tak, że oba zastosowania działa?
Jeśli deklarują jako
void print_stream(istream& is);
wówczas drugi zastosowanie nie będzie opracować ponieważ RValue nie będą wiązać się z const odniesieniu lwartości.
Jeśli deklarują jako
void print_stream(istream&& is);
czym pierwsze użycie nie kompilacji ponieważ lwartością nie będą wiązać się z odniesieniem RValue.
Gdybym zadeklarować ją jako
void print_stream(const istream& is);
następnie wdrożenie danej funkcji nie będzie kompilować, ponieważ nie można odczytać z const istream
.
Nie mogę uczynić z funkcji szablonu i użyć "uniwersalnego odniesienia", ponieważ jego implementacja musi być osobno skompilowana.
mogę dostarczyć dwa przeciążeń:
void print_stream(istream& is);
void print_stream(istream&& is);
i mieć drugiego naboru w pierwszym, ale to wydaje się dużo niepotrzebnej boilerplate, i uważam, że to bardzo niefortunne, aby to zrobić za każdym razem kiedy napisz funkcję z taką semantyką jak ta.
Czy jest coś lepszego, co mogę zrobić?
Mogłeś mieć pusty wydruk (Wrapper) i przenieść problem do konstruktora Wrapper, co ma sens tylko wtedy, gdy chcesz zrobić to samo dla kilku funkcji. –
"za każdym razem, gdy piszę funkcję z taką semantyką"? Czy często piszemy funkcje, które muszą przyjmować niestanowiący stałej nieciągłości argument, i muszą być wywoływalne zarówno z parametrem tymczasowym, jak i lwartościowym? Jest to dość specyficzny przypadek, a nie taki, w którym bym się martwił "za każdym razem, gdy muszę napisać funkcję z taką semantyką". Jeśli parametr można skopiować, możesz po prostu przekazać go według wartości. Jeśli nie musiałeś wywoływać na nim funkcji niestanowiących stałych, mógłbyś przejść przez referencję do konstelacji – jalf
Możesz napisać pomocnik rzucający "szablon T & stay (T && t) {return t; } 'i użyj' stay (fstream {"filename"}) '. –