A
Alfredo Di Napoli
Hi everyone!
Lately I am facing a problem with templates and iterators, but first
let me describe what I'm trying to do, so that my question is clearer.
I have one common class, MemoryObj<T>, and every memory management
class derive from it.
Now, I need to define two different classes: a "buffer" and a
"fundamental type". The first one, Buffer<T>, is a list of
MemoryChunk<T> stored as a std::vector< MemoryChunk<T>* >, while
Fundamental<T> is a wrapper to fundamental types (e.g., int, long,
double, ...), and for compatibility, it inherits from MemoryObj<T>, as
I already said.
The hard part: I want to implement iterator support for these classes.
So, I tried to add a simple iterator facility in my classes:
template<typename T, class Iterator = typename
std::vector<T>::iterator>
class MemoryObj
{
public:
typedef Iterator iterator;
virtual Iterator begin() = 0;
virtual Iterator end() = 0;
private:
};
Then, my memory chunk class will simply use std::vector<T>::iterator
to access its elements:
template <typename T, class Iterator = typename
std::vector<T>::iterator>
class MemoryChunk: public MemoryObj<T, Iterator>
{
public:
MemoryChunk(const std::vector<T>& vector): b_(vector) { }
size_t const size() const { return b_.size(); }
T& operator[](size_t i){ return b_; }
const T& operator[](size_t i) const{ return b_; }
typedef Iterator iterator;
iterator begin() { return b_.begin(); }
iterator end() { return b_.end(); }
private:
std::vector<T> b_;
};
And finally, my custom iterator for Buffer<T>:
template <typename T>
class BufferIterator: public std::vector<T>::iterator
{
public:
BufferIterator() { /* Code */ }
BufferIterator operator=( const BufferIterator& rhs ) { /* Code
*/ }
BufferIterator static begin(std::vector<MemoryChunk<T>*>& v) { /*
Code */ }
BufferIterator static end(std::vector<MemoryChunk<T>*>& v) { /*
Code */ }
T& operator*() { /* Code */ }
BufferIterator operator++(int) { /* Code */ }
BufferIterator& operator++() { /* Code */ }
BufferIterator operator+(const int n) { /* Code */ }
bool operator!=(const BufferIterator& b) const { /* Code */ }
private:
int currentChunk_;
int globalCounter_;
int stepCounter_;
T currentValue_;
std::vector<MemoryChunk<T> *>* vec_;
};
template <typename T, class Iterator = BufferIterator<T> >
class Buffer: public MemoryObj<T,Iterator>
{
public:
Buffer() { }
void push_back(MemoryChunk<T>& c) { chunks_.push_back(&c); }
size_t const size() const
{
size_t s = 0;
for (int i = 0; i < chunks_.size(); i++) {
s += chunks_->size();
}
return s;
}
MemoryChunk<T>& chunks(size_t idx) { return *chunks_[idx]; }
typedef Iterator iterator;
iterator begin(){ return iterator::begin(chunks_); }
iterator end(){ return iterator::end(chunks_); }
private:
std::vector<MemoryChunk<T>*> chunks_;
};
The iterators works fine... until I try to use functions that, as a
generic as I want my code to be, take as argument a MemoryObj<T>&, and
pass to these a Buffer<T>:
template <typename T>
void static genericFunction(MemoryObj<T>& obj)
{
typename MemoryObj<T>::iterator i = obj.begin();
std::cout << "The generic value is: " << *(i) << std::endl;
}
int main()
{
//Data creation
std::vector<int> v1(6,23);
std::vector<int> v2(4,18);
MemoryChunk<int> m1(v1);
MemoryChunk<int> m2(v2);
Buffer<int> b1;
b1.push_back(m1); b1.push_back(m2);
//Attempts with iterators over Buffer<T> work like a charm!
Buffer<int>::iterator it = b1.begin();
std::cout << "Simple access with operator* : ";
for (int i = 0; i < b1.size(); i++) {
int tmp = (*it);
std::cout << tmp << " ";
it++;
}
std::cout << std::endl;
//Invoke a generic function HUGE FAILURE!
std::cout << "Calling the generic function on MemoryChunk : " <<
std::endl;
genericFunction(m1); // This works just fine
std::cout << "Calling the generic function on Buffer : " <<
std::endl;
genericFunction(b1); //---> THIS FAILS
return 0;
}
Compiling the code, I get an error which I can't decrypt:
candidate function [with T = int] not viable: no known conversion
from 'Buffer<int>' to 'MemoryObj<int> &' for 1st argument [3]
I suspect the problem is related to the BufferIterator, cause
MemoryObj and MemoryChunk use a different iterator type (a
std::vector<T>::iterator), so the compiler doesn't know how to perform
the conversion. What am I doing wrong with my classes?
I am puzzled by this, and any help will be deeply appreciated!
You can download the source code on SourceForge at the following URL:
http://sourceforge.net/p/laetus/code/132/tree/branches/buffer-iterators/laetus-iterators/iterators/
Thanks a lot!
Alfredo
Lately I am facing a problem with templates and iterators, but first
let me describe what I'm trying to do, so that my question is clearer.
I have one common class, MemoryObj<T>, and every memory management
class derive from it.
Now, I need to define two different classes: a "buffer" and a
"fundamental type". The first one, Buffer<T>, is a list of
MemoryChunk<T> stored as a std::vector< MemoryChunk<T>* >, while
Fundamental<T> is a wrapper to fundamental types (e.g., int, long,
double, ...), and for compatibility, it inherits from MemoryObj<T>, as
I already said.
The hard part: I want to implement iterator support for these classes.
So, I tried to add a simple iterator facility in my classes:
template<typename T, class Iterator = typename
std::vector<T>::iterator>
class MemoryObj
{
public:
typedef Iterator iterator;
virtual Iterator begin() = 0;
virtual Iterator end() = 0;
private:
};
Then, my memory chunk class will simply use std::vector<T>::iterator
to access its elements:
template <typename T, class Iterator = typename
std::vector<T>::iterator>
class MemoryChunk: public MemoryObj<T, Iterator>
{
public:
MemoryChunk(const std::vector<T>& vector): b_(vector) { }
size_t const size() const { return b_.size(); }
T& operator[](size_t i){ return b_; }
const T& operator[](size_t i) const{ return b_; }
typedef Iterator iterator;
iterator begin() { return b_.begin(); }
iterator end() { return b_.end(); }
private:
std::vector<T> b_;
};
And finally, my custom iterator for Buffer<T>:
template <typename T>
class BufferIterator: public std::vector<T>::iterator
{
public:
BufferIterator() { /* Code */ }
BufferIterator operator=( const BufferIterator& rhs ) { /* Code
*/ }
BufferIterator static begin(std::vector<MemoryChunk<T>*>& v) { /*
Code */ }
BufferIterator static end(std::vector<MemoryChunk<T>*>& v) { /*
Code */ }
T& operator*() { /* Code */ }
BufferIterator operator++(int) { /* Code */ }
BufferIterator& operator++() { /* Code */ }
BufferIterator operator+(const int n) { /* Code */ }
bool operator!=(const BufferIterator& b) const { /* Code */ }
private:
int currentChunk_;
int globalCounter_;
int stepCounter_;
T currentValue_;
std::vector<MemoryChunk<T> *>* vec_;
};
template <typename T, class Iterator = BufferIterator<T> >
class Buffer: public MemoryObj<T,Iterator>
{
public:
Buffer() { }
void push_back(MemoryChunk<T>& c) { chunks_.push_back(&c); }
size_t const size() const
{
size_t s = 0;
for (int i = 0; i < chunks_.size(); i++) {
s += chunks_->size();
}
return s;
}
MemoryChunk<T>& chunks(size_t idx) { return *chunks_[idx]; }
typedef Iterator iterator;
iterator begin(){ return iterator::begin(chunks_); }
iterator end(){ return iterator::end(chunks_); }
private:
std::vector<MemoryChunk<T>*> chunks_;
};
The iterators works fine... until I try to use functions that, as a
generic as I want my code to be, take as argument a MemoryObj<T>&, and
pass to these a Buffer<T>:
template <typename T>
void static genericFunction(MemoryObj<T>& obj)
{
typename MemoryObj<T>::iterator i = obj.begin();
std::cout << "The generic value is: " << *(i) << std::endl;
}
int main()
{
//Data creation
std::vector<int> v1(6,23);
std::vector<int> v2(4,18);
MemoryChunk<int> m1(v1);
MemoryChunk<int> m2(v2);
Buffer<int> b1;
b1.push_back(m1); b1.push_back(m2);
//Attempts with iterators over Buffer<T> work like a charm!
Buffer<int>::iterator it = b1.begin();
std::cout << "Simple access with operator* : ";
for (int i = 0; i < b1.size(); i++) {
int tmp = (*it);
std::cout << tmp << " ";
it++;
}
std::cout << std::endl;
//Invoke a generic function HUGE FAILURE!
std::cout << "Calling the generic function on MemoryChunk : " <<
std::endl;
genericFunction(m1); // This works just fine
std::cout << "Calling the generic function on Buffer : " <<
std::endl;
genericFunction(b1); //---> THIS FAILS
return 0;
}
Compiling the code, I get an error which I can't decrypt:
candidate function [with T = int] not viable: no known conversion
from 'Buffer<int>' to 'MemoryObj<int> &' for 1st argument [3]
I suspect the problem is related to the BufferIterator, cause
MemoryObj and MemoryChunk use a different iterator type (a
std::vector<T>::iterator), so the compiler doesn't know how to perform
the conversion. What am I doing wrong with my classes?
I am puzzled by this, and any help will be deeply appreciated!
You can download the source code on SourceForge at the following URL:
http://sourceforge.net/p/laetus/code/132/tree/branches/buffer-iterators/laetus-iterators/iterators/
Thanks a lot!
Alfredo