Lambda auf vector anwenden


  • Mod

    DrakoXP schrieb:

    Wo genau?

    [](int number) -> pair<int, bool> { return make_pair(number, !!(number % 2)); }
    

    Btw. gibt deine Variante generell ein mapped_range zurück, was zwar seine Iteratoren hat, aber nicht diese einfache Schreibweise erlaubt:

    Offensichtlich nicht. Ich habe einfach den Iterator-Teil vorgezeigt.


  • Mod

    Hier mal ein anderer Vorschlag:

    #include <boost/iterator/transform_iterator.hpp>
    
    template <typename Func, typename Iterator>
    class mapped_range
    {
    	Func f;
    	Iterator first, last;
    
    	Func getFunctor() {return std::forward<Func>(f);}
    
    public:
    
    	mapped_range(Func f, Iterator const& first, Iterator const& last) :
    		f(std::forward<Func>(f)), first(first), last(last) {}
    
    	using iterator = boost::transform_iterator<Func, Iterator>;
    
    	iterator begin() {return {first, getFunctor()};}
    	iterator end  () {return {last, getFunctor()};}
    
    	template <typename Container>
    	operator Container()
    	{
    		return {begin(), end()};
    	}
    };
    
    #include <iterator>
    #include <type_traits>
    
    template <typename Func, typename Range>
    auto map(Func&& f, Range& r) -> mapped_range<typename std::remove_reference<Func>::type, decltype(std::begin(r))>
    {
    	return {std::forward<Func>(f), std::begin(r), std::end(r)};
    }
    
    template <typename Func, typename Range>
    auto map_ref(Func& f, Range& r) -> mapped_range<Func&, decltype(std::begin(r))>
    {
    	return {f, std::begin(r), std::end(r)};
    }
    
    template <typename Func, typename Range>
    auto map_funptr(Func* f, Range& r) -> mapped_range<Func*, decltype(std::begin(r))>
    {
    	return {f, std::begin(r), std::end(r)};
    }
    
    #include <cmath>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstdio>
    
    int main()
    {
    	std::vector<int> numbers = { 42, 23, 1337 };
    	for (p : map([](int number) { return std::make_pair(number, !!(number % 2)); }, numbers))
    		std::cout << p.first << " is " << (p.second ? "odd" : "even") << "\n";
    
    	std::vector<float> converted_numbers = map([] (int i) {return std::sin(float(i));}, numbers);
    	for (f : converted_numbers)
    		std::printf("%.4f, ", f); // Nathan kriegt Tollwut
    }
    


  • Sieht schon mal nicht schlecht aus. Was ich persönlich auf jeden Fall wollen würde ist Folgendes:

    auto sqrts = map(std::sqrt, unique(filter(isEven, map(toInt, myStringVector))));
    

    Sollte mit Arcoths Lösung gut möglich sein. 👍
    Vor allem ohne sinnlose Temporaries. Top.

    Gerade Lust mich an eine kleine Lib für den Hausgebrauch zu setzen. 😋



  • meine finale Version mit map und grep.
    http://ideone.com/V4yixa

    Das to<type> ist drin, weilstd::string zu viele nicht-explizite Konstruktoren hat und der Compiler sich da nicht entscheiden kann 😕

    Desweiteren kommt das Ganze ohne Boost aus.

    Für einfache Funktionszeiger an Stelle von Lambdas könnte man noch etwas einbauen
    und ich fürchte, dass generic lambdas aus C++14 hier auch Probleme machen könnten,
    aber so funktionieren schonmal einige fancy Sachen 🙂



  • DrakoXP schrieb:

    Für einfache Funktionszeiger an Stelle von Lambdas könnte man noch etwas einbauen
    und ich fürchte, dass generic lambdas aus C++14 hier auch Probleme machen könnten,
    aber so funktionieren schonmal einige fancy Sachen 🙂

    Geht doch bereits mit Funktionszeigern?


Anmelden zum Antworten