Initialisierung von vector<T> in C++11
-
Folgende Situation:
Ich habe Klassen T, S mit einem
T operator+(T t, S s)und einen vector<T>, den ich als Konstante initialisieren will mit
{T(0) + S(0), T(0) + S(1), T(0) + S(2), ..., T(0) + S(10)}Kann man das in C++11 und lambda funktions so elegant wie mit Lisp und mapcar machen?
-
wat
-
wat wat?
Ich will sowas wie
(mapcar #'(lambda (n) (+ n 1337)) (0 1 2 3 4))haben.
-
Mal in Code gefasst:
struct foo {}; struct bar {}; foo operator + (foo, bar); std::vector<foo> v1; std::vector<bar> v2; std::vector<foo> v3; // soll jetzt die werte von v1 und v2 addiert enthalten?Habe ich dich richtig verstanden?
-
Fast: v3 soll die Inhalte von einem festen foo addiert zu allen Werten von v2 enthalten.
-
struct foo{}; struct bar{}; foo operator + (foo, bar); std::vector<foo> values; bar to_add; std::vector<foo> result; std:transform ( values.begin(), values.end(), std::back_inserter(result), [&] (foo f) { return f + to_add; } );Sowas?
-
Fast: Es soll aber für die Initialisierung für eine *Konstante* const vector <foo> sein, d.h. es muss in eine Zeile passen.
-
std::vector<foo> gimmetheresult() { std::vector<foo> result; .... return result; } const std::vector<foo> myvalues(gimmetheresult());
-
Thx! Das scheint zu funzen.
-
Darf ich fragen womit du c++11 . Hast du ein Tutorial oder so und welchen compiler benutzt du ?
Wurde mich sehr freuen wenn dus mir sagen konntest !
-
Ich verwende den g++ 4.6.2 auf Fedora Linux 64.
-
Wenn es Ranges gäbe, würde mir das hier fast noch besser gefallen.
#include <iostream> #include <functional> #include <iterator> #include <algorithm> #include <vector> struct foo { int value; foo(int value) : value(value) {} }; struct bar { int value; bar(int value) : value(value) {} }; foo operator + (foo f, bar b) { return foo(f.value + b.value); } template <typename Iterator, typename OutType> struct transforming_iterator : std::iterator<std::input_iterator_tag, OutType> { typedef typename Iterator::value_type in_type; Iterator iter; std::function<OutType(in_type const&)> transform; transforming_iterator(Iterator iter, std::function<OutType(in_type const&)> const& transform) : iter(iter) , transform(transform) {} OutType operator * () const { return transform(*iter); } transforming_iterator& operator ++ () { ++iter; return *this; } transforming_iterator operator ++ (int) { transforming_iterator tmp(*this); ++*this; return tmp; } friend bool operator == (transforming_iterator const& first, transforming_iterator const& second) { return first.iter == second.iter; } friend bool operator != (transforming_iterator const& first, transforming_iterator const& second) { return !(first == second); } }; template <typename InType, typename OutType, typename Iterator> transforming_iterator<Iterator, OutType> make_transforming_iterator(Iterator iter, std::function<OutType(InType const&)> const& transform) { return transforming_iterator<Iterator, OutType>(iter, transform); } int main() { std::vector<bar> bars; int init = 0; std::generate_n(std::back_inserter(bars), 20, [&] () { return bar(init++); }); foo const to_add(42); auto transform = [&] (bar const& b) { return to_add + b; }; std::vector<foo> const foos(make_transforming_iterator<bar, foo>(bars.begin(), transform), make_transforming_iterator<bar, foo>(bars.end(), transform)); for(foo const& f : foos) std::cout << f.value << '\n'; }Und generate_n könnte man auch noch durch einen generating_iterator ersetzen. Das hätte den Vorteil, dass ich den vector<bar> nicht bräuchte, also die Werte nichtmal im Speicher liegen müssten. Iteratoren in C++ sind halt einfach sexy

-
c++11 rulez schrieb:
Ich will sowas wie
(mapcar #'(lambda (n) (+ n 1337)) (0 1 2 3 4))haben.
Dann baue dir doch eine mapcar-Funktion als Template, wenn dir http://www.cplusplus.com/reference/algorithm/transform/ zu lang ist.
Fast: Es soll aber für die Initialisierung für eine *Konstante* const vector <foo> sein, d.h. es muss in eine Zeile passen.
Dumme Begruendung. Zusaetzlich ist die Laenge einer Zeile unterschiedlich von Fall zu Fall.