11

Is it possible to create an STL-like container, or even just an STL-style iterator, for an existing array of POD-type elements?

For example, suppose I have an array of ints. It would be convenient to be able to call some of the STL functions, such as find_if, count_if, or sort directly on this array.

Non-solution: copying the entire array, or even just references to the elements. The goal is to be very memory- and time-saving while hopefully allowing use of other STL algorithms.

Martin York
  • 257,169
  • 86
  • 333
  • 562
Tyler
  • 28,498
  • 11
  • 90
  • 106
  • "For example, suppose I have an array of ints. It would be convenient to be able to call some of the STL functions, such as find_if, count_if, or sort directly on this array." You can. All of the above. – moswald Oct 06 '08 at 21:12

5 Answers5

23

You can call many of the STL algorithms directly on a regular C style array - they were designed for this to work. e.g.,:

int ary[100] = ...;
// init ...
    
// note: technically, std::begin(ary) can just be ary in this context
std::sort(std::begin(ary), std::end(ary));        // sort the array
std::find(std::begin(ary), std::end(ary), pred);  // find some element

// or since C++20:
std::rangs::sort(ary);
std::ranges::find(ary, pred);

I think you'll find that most stuff works just as you would expect.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
6

You can use an inline function template so that you don't have to duplicate the array index

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];
  // any standard
  std::find(array_begin(array), array_end(array), 10);
  // or, since C+11
  std::find(std::begin(array), std::end(array), 10);
  // or, since C++20
  std::ranges::find(array, 10);
}
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Richard Corden
  • 21,389
  • 8
  • 58
  • 85
5

All the STL algorithms use iterators.
A pointer is a valid iterator into an array of objects.

N.B.The end iterator must be one element past the end of the array. Hence the data+5 in the following code.

#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"));
}
Martin York
  • 257,169
  • 86
  • 333
  • 562
4

You can use Boost.Array to create a C++ array type with STL semantics.

using arrays:

int a[100];
for (int i = 0; i < 100; ++i)
    a[i] = 0;

using boost.arrays:

boost::array<int,100> a;
for (boost::array<int,100>::iterator i = a.begin(); i != a.end(); ++i)
    *i = 0;

Update: With C++11, you can now use std::array.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
2

A pointer is a valid model of an iterator:

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;
}
Matt Price
  • 43,887
  • 9
  • 38
  • 44