Pregunta

Me gustaría ser capaz de escribir algo como

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

La función transform parece ser similar, pero no va a autogenerar el tamaño de la colección resultante.

¿Fue útil?

Solución

Puede utilizar std::back_inserter en <iterator>, aunque proporciona el tamaño delante es más eficiente. Por ejemplo:

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

Otros consejos

Esta pregunta se hizo antes de que el C ++ 11 estándar entró en vigor hoy en día ... tenemos std::transform() como el (feo) equivalente de un 'mapa' de programación funcional. He aquí cómo se usa:

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

Para que esto funcione, necesitará las siguientes observaciones:

  1. Para realizar la asignación eficiente, la función debe map no hacer el trabajo. En su lugar, debe guardar sus argumentos en un objeto temporal (en su caso, eso sería una instancia de class map::result<char(*)(char), vector<char> >)
  2. Esta map::result temporal debe tener una conversión template <typename T> operator T.
  3. Cuando se asigna el map::result a un std::vector<char>, esta conversión es la única viable.
  4. En el class map::result<char(*)(char), vector<char> >::operator vector<char> operador de conversión que tiene el tipo de entrada y de retorno, y la función de mapeo. En este punto se puede transformar de manera efectiva las entradas.

<edit>

Código

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

Uso de esta manera:

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>();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top