Question

Je voudrais pouvoir écrire quelque chose comme

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

La fonction transform semble être similaire, mais il ne sera pas la taille autogenerate de la collection résultante.

Était-ce utile?

La solution

Vous pouvez utiliser std::back_inserter dans <iterator>, bien que fournir la taille en face est plus efficace. Par exemple:

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

Autres conseils

Cette question a été posée la norme C ++ 11 est entré en vigueur ... Aujourd'hui, nous avons std::transform() comme (laid) équivalent d'une programmation fonctionnelle « carte ». Voici comment l'utiliser:

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);

Pour faire ce travail, vous aurez besoin des observations suivantes:

  1. Pour l'affectation efficace, la fonction doit map pas faire le travail. Au lieu de cela, il doit enregistrer ses arguments dans un objet temporaire (dans votre cas, ce serait une instance de class map::result<char(*)(char), vector<char> >)
  2. Cette map::result temporaire devrait avoir une conversion template <typename T> operator T.
  3. Lorsque le map::result est affecté à un std::vector<char>, cette conversion est la seule viable.
  4. Dans l'opérateur de conversion class map::result<char(*)(char), vector<char> >::operator vector<char> vous avez le type d'entrée et le retour, et la fonction de cartographie. À ce stade, vous pouvez transformer efficacement les entrées.

<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);
}

Utiliser comme ceci:

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>();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top