STL não copiar invólucro em torno de uma matriz existente?
Pergunta
É possível criar um recipiente STL-like, ou mesmo apenas uma iteração de estilo STL, para uma matriz existente de elementos POD do tipo?
Por exemplo, suponha que eu tenho um array de inteiros. Seria conveniente para ser capaz de chamar algumas das funções STL, como find_if, count_if, ou classificar diretamente sobre essa matriz.
Não-solução: a cópia de toda a matriz, ou mesmo apenas referências aos elementos. O objetivo é ser muito memória- e enquanto esperamos permitindo o uso de outros algoritmos STL de economia de tempo.
Solução
Você pode chamar muitos dos algoritmos de STL diretamente em uma matriz regular estilo C - eles foram projetados para que isso funcione. . Por exemplo,:
int ary[100];
// init ...
std::sort(ary, ary+100); // sorts the array
std::find(ary, ary+100, pred); find some element
Eu acho que você verá que a maioria das coisas funciona exatamente como seria de esperar.
Outras dicas
Você pode usar um modelo de função em linha de modo que você não tem que duplicar o índice de array
template <typename T, int I>
inline T * array_begin (T (&t)[I])
{
return t;
}
template <typename T, int I>
inline T * array_end (T (&t)[I])
{
return t + I;
}
void foo ()
{
int array[100];
std::find (array_begin (array)
, array_end (array)
, 10);
}
Todos os algoritmos STL usar iteradores.
Um ponteiro é um iterador válido em um array de objetos.
NB. O fim iteração deve ser um elemento para além da extremidade da matriz. Daí a dados + 5 no código a seguir.
#include <algorithm>
#include <iostream>
#include <iterator>
int main()
{
int data[] = {4,3,7,5,8};
std::sort(data,data+5);
std::copy(data,data+5,std::ostream_iterator<int>(std::cout,"\t"));
}
Você pode usar Boost.Array para criar um tipo de matriz ++ C com semântica STL.
usando matrizes:
int a[100];
for (int i = 0; i < 100; ++i)
a[i] = 0;
usando boost.arrays:
boost::array<int,100> a;
for (boost::array<int,100>::iterator i = a.begin(); i != a.end(); ++i)
*i = 0;
Update:. Com C ++ 11, agora você pode usar std::array
Um ponteiro é um modelo válido de um iterador:
struct Bob
{ int val; };
bool operator<(const Bob& lhs, const Bob& rhs)
{ return lhs.val < rhs.val; }
// let's do a reverse sort
bool pred(const Bob& lhs, const Bob& rhs)
{ return lhs.val > rhs.val; }
bool isBobNumberTwo(const Bob& bob) { return bob.val == 2; }
int main()
{
Bob bobs[4]; // ok, so we have 4 bobs!
const size_t size = sizeof(bobs)/sizeof(Bob);
bobs[0].val = 1; bobs[1].val = 4; bobs[2].val = 2; bobs[3].val = 3;
// sort using std::less<Bob> wich uses operator <
std::sort(bobs, bobs + size);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
// sort using pred
std::sort(bobs, bobs + size, pred);
std::cout << bobs[0].val << std::endl;
std::cout << bobs[1].val << std::endl;
std::cout << bobs[2].val << std::endl;
std::cout << bobs[3].val << std::endl;
//Let's find Bob number 2
Bob* bob = std::find_if(bobs, bobs + size, isBobNumberTwo);
if (bob->val == 2)
std::cout << "Ok, found the right one!\n";
else
std::cout << "Whoops!\n";
return 0;
}