2016-09-29 1 views
6

Warum können Anrufe zu STL-Funktionen nicht kürzer sein? Ich wurde am cppreference.com im folgenden Codeausschnitt suchen:Warum müssen C++ STL-Funktionsaufrufe so ausführlich sein?

#include <string> 
#include <cctype> 
#include <algorithm> 
#include <iostream> 

int main() 
{ 
    std::string s("hello"); 
    std::transform(s.begin(), s.end(), s.begin(), 
        [](unsigned char c) { return std::toupper(c); }); 
    std::cout << s; 
} 

Es scheint mir, dass es möglich sein soll diesen Anruf mehr kurz zu machen. Die erste offensichtliche Sache wäre, das Lambda zu beseitigen:

std::string s("hello"); 
std::transform(s.begin(), s.end(), s.begin(), std::toupper); 
std::cout << s; 

Aber das funktioniert nicht. Da Sie in der Regel einen ganzen Container konvertieren möchte, sollte es möglich sein, einfach zu bedienen, dass als Parameter:

std::string s("hello"); 
std::transform(s, s.begin(), std::toupper); 
std::cout << s; 

Sie auch die Ausgabe Iterator weglassen könnte das Ergebnis von Wert zurück:

std::string s("hello"); 
std::cout << std::transform(s, std::toupper); 

Bei dieser Punkt die temporäre Variable ist nicht notwendig:

std::cout << std::transform("hello"s, std::toupper); 

Mit zusätzlicher Lesbarkeit:

using namespace std; 
cout << transform("hello"s, toupper); 

Wäre das nicht lesbarer und schöner? Warum waren STL-Funktionen nicht so konzipiert, dass es möglich war, einen kurzen Code wie diesen zu schreiben? Wird es möglich sein, diese Aufrufe in einer zukünftigen Version des C++ - Standards zu verkürzen?

+4

Für Ihre letzten beiden Beispiele ' "Hallo"' hat den Typ 'const char [N]' was bedeutet, es ist nicht modifizierbar. – NathanOliver

+3

Für den Anfang können Sie nicht einfach 'std :: toupper' auf 'char's wegen Sachen von seiner C-Vergangenheit benutzen. [Details] (https://stackoverflow.com/questions/21805674/do-i-need-to-cast-to-unsigned-char-before-calling-toupper). –

+2

beim Verkürzen der Dinge und Entfernen der "Ende" Iterator etc. Sie machen es vielleicht weniger ausführlich für die meisten Fälle, aber Sie "entfernen" die Fälle, in denen es nicht so ist. C++ kann sehr flexibel und elegant sein, da Sie Operationen einen Start- und End-Iterator geben. – Hayt

Antwort

5

Leider hat std::toupper überlastet, so dass das Lambda die Problemumgehung ist.

Dann mit range-v3, können Sie es vereinfachen:

auto to_upper = [](unsigned char c) { return std::toupper(c); }; // To handle overloads 
std::cout << std::string("Hello world" | ranges::view::transform(to_upper)) 
      << std::endl; 

Demo

2
std::transform(s.begin(), s.end(), s.begin(), 
       [](unsigned char c) { return std::toupper(c); }); 

Die allgemeine Form funktioniert einfach. Immer!

Sie können es an Ort und Stelle oder in ein separates Ergebnis zu verwandeln:
std::transform(s.begin(), s.end(), result.begin(),....

Es kann den ganzen Container oder nur einen Teil verwandeln. Jeder Teil Ihrer Wahl:
std::transform(s.begin() + i, s.begin() + j, s.begin() + i,...

Und es funktioniert auf jede Sequenz, auch wenn die Elemente nicht Teil eines Behälters.

Also die allgemeine Form würde sowieso benötigt werden, da es die nützlichste ist.

+1

Ich verstehe die Notwendigkeit für die allgemeine Form. Ich bin daran interessiert zu wissen, warum es zumindest keine anderen Formen gibt. – Szabolcs

Verwandte Themen