patterncppMinor
Using a template to cycle through a sequence of containers
Viewed 0 times
cycletemplatesequenceusingthroughcontainers
Problem
I'm trying to implement a template that takes a container as parameter. The template has a
Header:
Implementation:
Any improvement or potential issues to the code?
getnext method that cycles through the elements in the parameter. Take note that I'm not using C++11.Header:
#pragma once
template class TContainer, class TObject>
class cycle
{
public:
explicit cycle( TContainer> & container )
: mContainer( container ), index(0) {}
TObject getNext(int numObjectsToCycle)
{ return mContainer[index++ % numObjectsToCycle]; }
private:
TContainer> & mContainer;
int index;
};Implementation:
#include
#include
#include "cycle.h"
using namespace std;
class Processor
{
int mIndex;
vector numbers;
public:
cycle cycler;
// Is it safe to pass numbers since it is declared first??
Processor() : mIndex(0), cycler(numbers) {}
void update() { cout << numbers[mIndex++ % numbers.size()] << std::endl;}
void addNumber(int x) { numbers.push_back(x); }
};
int main()
{
Processor S;
for (int i = 0; i < 5; ++i)
{
S.addNumber(i+1);
}
cout << "using update" << endl;
for (int c = 0; c < 10; ++c)
{
S.update();
}
cout << "using cycle" << endl;
for (int c = 0; c < 10; ++c)
{
cout << S.cycler.getNext(5) << endl;
}
std::cin.get();
}Any improvement or potential issues to the code?
Solution
Here is how I would write it:
Notes:
-
The template parameter is the container,
-
The return type of
-
If I understand correctly from the title,
-
Why pass a parameter to
-
With only a few changes, here is
Notes:
Also, whenever you want to
for convenience, only do it inside another (your own) namespace, never globally.
EDIT
I just noticed you're not using C++11. In this case, just use
instead.
template
class cycle
{
C& mContainer;
size_t index;
using ref = decltype(mContainer[0]);
public:
explicit cycle(C& container) :
mContainer(container), index(0) {}
ref getNext()
{
return mContainer[index++ % mContainer.size()];
}
};Notes:
-
The template parameter is the container,
C. This not only simplifies code, but also works for containers that do not follow a specific pattern, e.g. have more parameters than just a value type and an allocator type.-
The return type of
getNext is automatically inferred from C. This is not just C's value_type but a (non-const) reference to it.-
If I understand correctly from the title,
C is supposed to be a sequence of containers? If so, the value_type is a container itself so it is even more important that a reference is returned from getNext.-
Why pass a parameter to
getNext? To cycle correctly, you should use mContainer.size(), exactly as you do in Processor::update, right?-
index is of type size_tWith only a few changes, here is
Processor:class Processor
{
size_t mIndex;
std::vector numbers;
public:
cycle> cycler;
Processor() : mIndex(0), numbers(), cycler(numbers) {}
void update() { std::cout << numbers[mIndex++ % numbers.size()] << std::endl;}
void addNumber(int x) { numbers.push_back(x); }
};Notes:
- again,
mIndexis asize_t
cycleris acycle
numbersis default-initialized
cycleris safely constructed afternumbers
Also, whenever you want to
using namespace std;for convenience, only do it inside another (your own) namespace, never globally.
EDIT
I just noticed you're not using C++11. In this case, just use
typedef typename C::value_type& ref;instead.
Code Snippets
template<typename C>
class cycle
{
C& mContainer;
size_t index;
using ref = decltype(mContainer[0]);
public:
explicit cycle(C& container) :
mContainer(container), index(0) {}
ref getNext()
{
return mContainer[index++ % mContainer.size()];
}
};class Processor
{
size_t mIndex;
std::vector<int> numbers;
public:
cycle<std::vector<int>> cycler;
Processor() : mIndex(0), numbers(), cycler(numbers) {}
void update() { std::cout << numbers[mIndex++ % numbers.size()] << std::endl;}
void addNumber(int x) { numbers.push_back(x); }
};using namespace std;typedef typename C::value_type& ref;Context
StackExchange Code Review Q#48110, answer score: 3
Revisions (0)
No revisions yet.