Domanda

I have legacy code where a similar method is used to cycle through a sequential container (vector in this example. Some implementations use other kinds of containers). So I factored it out into a template so I could reuse the same piece of code for any container type.

template<template<class, class> class TContainer, class TObject>
class cycle
{
public:

    explicit cycle( TContainer<TObject, std::allocator<TObject>> & container )
        : mContainer( container ), index(0) {}

    TObject getNext(int numObjectsToCycle) 
    { return mContainer[index++ % numObjectsToCycle]; }
private:
    TContainer<TObject, std::allocator<TObject>> & mContainer;
    int index;
};

Then my class has a cycler to cycle through my variable numbers.

class myClass
{
   std::vector<int> numbers;

public:
   cycle<vector, int> cycler;
   // Is it safe to pass numbers since it is declared first??
   myClass() : cycler(numbers) {} 

};

Then, I use the code like below.:

myObject.cycler.getNext(size);

Is it a good programming practice to pass the vector "numbers" to cycler? Is there a better way of implementing my template?

The code really is to be able to infinitely loop through objects. My class is invoked from external code that just calls a member method, and I want to be able to just call getNext() so I wouldn't have to use an index.

È stato utile?

Soluzione

In the standard library another "pattern" exists and it's the iterator pattern. Basically every container type implements begin and end which returns, respectively, the iterator to the first element and the past-the-end element (which is always guaranteed to exists).

This works for every container type, from std::vector to std::array including C-style arrays with std::begin and std::end. If you want to loop in a generic container you can do, for example:

template<typename Container>
void cicle(Container const& c) {
    for (auto const& i : c) {
        // …
    }
}

or, to better visualize the pattern:

template<typename Container>
void cicle(Container const& c) {
    for (auto it = std::begin(c); it != std::end(c); ++it) {
        // …
    }
}

Live demo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top