Frage

Ich möchte etwas schreiben können, wie

char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);

Die transform Funktion erscheint ähnlich zu sein, aber es wird die Größe der resultierenden Sammlung nicht automatisch generieren.

War es hilfreich?

Lösung

Sie können std::back_inserter in <iterator> verwenden, obwohl vor der Größe Bereitstellung effizienter ist. Zum Beispiel:

string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"

Andere Tipps

Diese Frage gestellt wurde, bevor die C ++ 11-Standard in Kraft getreten ist ... heute haben wir std::transform() als (hässlich) äquivalent eine funktionale Programmierung ‚Landkarte‘. Hier ist, wie es zu benutzen:

auto f(char) -> char; // or if you like: char f(char)
vector<char> bar;
vector<char> foo;
// ... initialize bar somehow ...
std::transform(bar.begin(), bar.end(), std::back_inserter(foo), f);

Um diese Arbeit zu machen, müssen Sie die folgenden Beobachtungen:

  1. Um die Zuordnung effizienter zu gestalten, sollte die map Funktion nicht die Arbeit machen. Stattdessen sollten sie ihre Argumente in einem temporären Objekt speichern (in Ihrem Fall, das wäre eine Instanz von class map::result<char(*)(char), vector<char> > sein)
  2. Diese map::result temporären sollte eine template <typename T> operator T Umwandlung hat.
  3. Wenn die map::result zu einem std::vector<char> zugeordnet ist, ist diese Umwandlung der einzig gangbare.
  4. Bei der Umwandlung Operator class map::result<char(*)(char), vector<char> >::operator vector<char> Sie die Eingabe und Rückgabetyp haben, und die Abbildungsfunktion. An dieser Stelle können Sie die Eingaben wirksam umwandeln können.

<edit>

Code

template<typename CONT, typename FUNC>
class mapresult {
    CONT const& in;
    FUNC f;
public:
    template<typename RESULT> RESULT to() const
    {
        RESULT out;
        for (auto const& e : in) { out.push_back(f(e)); }
        return out;
    }
    template<typename RESULT> operator RESULT() const
    {
        return this->to<RESULT>();
    }
    mapresult(CONT const& in, FUNC f) : in(in), f(std::move(f)) { }
};

template<typename CONT, typename FUNC>
auto map(CONT const& in, FUNC f) -> mapresult<CONT, FUNC>
{
    return mapresult<CONT, FUNC>(in, f);
}

Verwenden Sie wie folgt aus:

using namespace std;
char foo(char c) { return c | ('A' ^ 'a'); }
std::string in = "Test";

int main(int argc, char* argv[])
{
    string out = map(in, &foo);
    cout << out << endl;

    char replace = 'e';
    cout << map(in, [replace](char c){return c == replace ? '?' : c; }).to<string>();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top