Funktiosta on kaksi versiota, joista jälkimmäinen käyttää funktiota operator+ __binary_op:na. Laskeminen aloitetaan alkuarvosta __init.
_Tp std::accumulate(_InputIterator __first,Algoritmin käyttäminen on helppoa, kun säiliössä on tavallisia numeroita:
_InputIterator __last,
_Tp __init,
_BinaryOperation __binary_op
)
_Tp std::accumulate(_InputIterator __first,
_InputIterator __last,
_Tp __init
)
#include <iostream>
#include <numeric>
#include <list>
int main()
{
std::list<float> lista;
lista.push_back(3);
lista.push_back(4);
lista.push_back(4);
std::cout << std::accumulate(lista.begin(), lista.end(), 1) << std::endl;
}
Ohjelma antaa kääntyessään varoituksen:
In function ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp) [with _InputIterator = std::_List_iterator<float>, _Tp = int]
warning: converting to ‘int’ from ‘float’
Se korjaantuukin vaihtamalla 1:n tilalle
static_cast<float>(1).Ohjelma tulostaa 12 (3+4+4 = 11 ja alkuarvona 1).
Accumulaten käyttö oman luokan kanssa
Jos yhteen halutaan laskea muutakin kuin perustietotyyppejä täytyy määritellä operator+. Jos laskettavana on luokkia X, täytyy operator+ määritellä seuraavasti int operator+(int, const X &).Tässä luokka, jonka sisältöä lasketaan:
class X {
public:
X(int i):m_i(i) { }
int get_i() const { return m_i; }
private:
int m_i;
};
operator+
Esimerkki:
int operator+(int n, const X &x) { return n + x.get_i(); }
std::vector<X> y;
y.push_back(1);
y.push_back(2);
int n = std::accumulate(y.begin(), y.end(), 0); // palauttaa 3
Tämä ei kuitenkaan toimi, jos säiliössä on osoittimia. Katso kaksi seuraavaa.
Muu funktio
Määritetään funktio, joka ottaa kaksi parametriä. Tässä on vikana, että se sotkee nimiavaruutta ja jos se määritellään väärässä paikassa niin sitä ei välttämättä osaa yhdistää oikeaan tarkoitukseen.Siirretäänkin se X-luokan funktioksi. Tällöin päästääm myös käsiksi
int plus(int i, X *x) {
return i + x->get_i();
}
m_i-muuttujaan ilman getteriä.
class X {
public:
static int plus(int i, X *x) {
return i + x->m_i;
}
};
std::vector<X*> x;
int n = std::accumulate(x.begin(), x.end(), 0, X::plus);
TR1
Laskeminen voidaan myös hoitaa C++:n seuraavaan standardiin lisättävien komponenttien avulla, jotka löytyvät GCC 4:stä. (TR1)Boost-kirjastoon tutustuneille koodi näyttää varmasti heti selvältä. Tämän ratkaisun huonoja puolia ovat verrattain pitkä kääntymisaika johtuen massiivisesta mallien (template) sekä ylikuormitusten käytön takia.
int n = std::accumulate(x.begin(), x.end(), 3,
std::tr1::bind(std::plus<int>(),
std::tr1::placeholders::_1,
std::tr1::bind(&X::get_i,
std::tr1::placeholders::_2)));
Esimerkkiohjelman voit ladata täältä: http://pastebin.ca/raw/186941
Ei kommentteja:
Lähetä kommentti