#include <iostream>
using namespace std;
template <class T>
class ring {
private:
T *m_values;
int m_size;
int m_index;
public:
class iterator;
public:
ring(int size):
m_size(size), m_index(0), m_values(NULL) {
m_values = new T[size];
}
~ring() {
delete [] m_values;
}
int size() const {
return m_size;
}
iterator begin() {
return iterator(0, *this);
}
iterator end() {
return iterator(m_size, *this);
}
void add(T value) {
m_values[m_index] = value;
m_index = (m_index + 1) % m_size;
}
T &get(int pos) {
return m_values[pos];
}
};
template<class T>
class ring<T>::iterator {
private:
int m_pos;
ring &m_ring;
public:
iterator(int m_pos, ring &m_ring): m_pos(m_pos), m_ring(m_ring) {};
iterator &operator++(int) {
m_pos++;
return *this;
}
iterator &operator++() {
m_pos++;
return *this;
}
bool operator!=(const iterator &other) {
return other.m_pos != m_pos;
}
T &operator*() {
return m_ring.get(m_pos);
}
};
Here is the c++ code. I am new to c++ and this codes at CLion gives me "Class iterator doesn't have a constructor iterator(int,ring)" at begin() and end() function. Can anone give me some hint about why this would happen even I have defined it?
BTW: This is from udemy "Learn Advanced C++ Programming" lecture 44.
UPDATE: Some comments find I didn't define and only declare. That's not the reason because I defined it in a separate .cpp file. I also tried to define it inline but still give me the same error message from CLion.
You declare the constructor here
iterator(int m_pos, ring &m_ring);
but there is no definition of this special member function. If you provide one, you're probably fine
iterator(int m_pos, ring &m_ring) : m_pos(m_pos), m_ring(m_ring)
{
/* Maybe some other stuff... */
}
You declared the interator(int, ring) but not defined it. That is the problem.
Declaration vs Definition:
A declaration provides basic attributes of a symbol: its type and its
name. A definition provides all of the details of that symbol--if it's
a function, what it does; if it's a class, what fields and methods it
has; if it's a variable, where that variable is stored. Often, the
compiler only needs to have a declaration for something in order to
compile a file into an object file, expecting that the linker can find
the definition from another file. If no source file ever defines a
symbol, but it is declared, you will get errors at link time
complaining about undefined symbols.
src: https://www.cprogramming.com/declare_vs_define.html
Related
An exception is thrown, access violation reading location.
I have overloaded all operators perfectly, and don't know the reason why is this happening.
The loop was working fine in the tutorial, but it's not running on my system.
Please help me, here's the code -
This is defined by me - ring.h
#pragma once
#ifndef RING_H_
#define RING_H_
#include<iostream>
using namespace std;
template<class T>
class ring
{
private:
int m_pos;
T* m_values;
int m_size;
public:
class iterator;
public:
ring(int size) : m_pos(0), m_size(size), m_values(NULL)
{
m_values = new T[size];
}
~ring()
{
delete[] m_values;
}
int size()
{
return m_size;
}
iterator begin()
{
return iterator(0, *this);
}
iterator end()
{
return iterator(m_size-1, *this);
}
void add(T value)
{
m_values[m_pos++] = value;
if (m_pos == m_size)
{
m_pos = 0;
}
}
T& get(int pos)
{
return m_values[pos];
}
};
template<class T>
class ring<T>::iterator
{
private:
int m_pos;
ring m_ring;
public:
iterator(int pos, ring &aRing): m_ring(aRing), m_pos(pos) {}
iterator& operator++(int)
{
m_pos++;
return *this;
}
T& operator*()
{
return m_ring.get(m_pos);
}
bool operator!=(const iterator& other) const
{
return m_pos != other.m_pos;
}
};
#endif //RING_H_
And here is file containing main function - (source.cpp)
#include<iostream>
#include"ring.h"
using namespace std;
int main()
{
ring<string> textring(3);
textring.add("One");
textring.add("Two");
textring.add("Three");
for (ring<string>::iterator it = textring.begin(); it != textring.end(); it++)
{
cout << *it << endl;
}
cout << endl;
/*for (string value : textring)
{
cout << value << endl;
}*/
}
The value 0xdddddddd is a well-known pattern of memory that have been passed to free (or delete). In other words, somewhere you're using memory that was allocated on the heap, but no longer is.
The problem is that your iterator class copies the ring object, but the ring class doesn't follow the rules of three, five or zero.
A simple solution (and probably best) is to not copy at all, but to store a reference to the ring object in the iterator class:
template<class T>
class ring<T>::iterator
{
private:
int m_pos;
ring& m_ring; // Reference to a "ring"
...
};
To future-proof the ring class I recommend that you take some time to study about the rules of three, five or zero.
I really recommend using std::vector and follow the rule of zero.
I created a ring buffer and I want to import that class to Python using boost. When I am trying to that its getting error.
ring.cpp: In function ‘void init_module_ring()’:
ring.cpp:130:16: error: wrong number of template arguments (1, should be 4)
class_<Ring>("Ring").Please help me. Thanks in Advance.
Here is my code:
#include <boost/python/def.hpp>
#include<iostream>
using namespace std;
using namespace boost::python;
template <class T>
class Ring
{
public:
class iterator;
public:
unsigned int m_size;
unsigned int pos;
T *val;
Ring():
m_size(0),pos(0),val(NULL){};
Ring(int size):m_size(size),pos(0){
val=new T[m_size];
};
Ring(const Ring &other)
{
this->m_size = other.m_size;
this->pos= other.pos;
this->val = other.val;
}
~Ring()
{
delete[] val;
}
void insert(T data)
{
val[pos]= data;
pos++;
if(pos==m_size)
pos=0;
}
void displayall()
{
for(int i =0;i<m_size;i++)
{
cout<<val[i]<<' ';
}
}
iterator begin()
{
return iterator(val);
}
iterator end()
{
return iterator(val + m_size);
}
unsigned int size()
{
return m_size;
}
void check()
{
cout<<val<<' ';
cout<<val+5;
}
};
template<class T>
class Ring<T>::iterator
{
T *it_value;
public:
iterator():it_value(NULL){};
iterator(T *value)
{
it_value = value;
};
iterator(const iterator &other)
{
this->it_value = other.it_value;
}
friend ostream& operator<<(ostream &out,iterator it)
{
out<<*it.it_value;
return out;
}
iterator operator++()
{
it_value +=1;
return (iterator(it_value));
}
iterator operator++(const int x)
{
it_value = it_value+ x+1;
return(iterator(it_value));
}
bool operator==(const iterator &other) const
{
return (*it_value == *(other.it_value));
};
bool operator!=(const iterator &other) const
{
return (!(*this == other));
};
iterator operator*()
{
return *this;
}
void display()
{
cout<<*it_value<<' ';
}
};
BOOST_PYTHON_MODULE(ring)
{
class_<Ring>("Ring")
template <class T>
.def(init<int>())
.def("insert", &Ring::insert)
.def("display_all", &Ring::displayall)
;
}
A template is not a class. You need to instantiate your template (i.e. Ring<int> instead of Ring).
class_<Ring<int>>("IntRing", init<int>())
.def("insert", &Ring<int>::insert)
.def("display_all", &Ring<int>::displayall)
;
Also, the template <class T> part in your original code:
class_<Ring>("Ring")
template <class T> // error
.def(init<int>())
.def("insert", &Ring::insert)
.def("display_all", &Ring::displayall)
;
is a syntax error. It suggests that you expect to be able to bind to the template in a generic manner, which is unfortunately not possible. The reason is that templates are instantiated at compile-time, i.e. the compiler needs to know the exact types the template is going to be used with. If you are interfacing with python, you can't know that in advance, because it be decided at runtime.
Under the hood, Boost.Python generates wrapper functions that take the PyObjects from python and convert them to strongly typed values for your parameters (and your return values back to PyObjects). It can only do it because it knows the types to convert the dynamic values to/from.
The best you can do is creating the class that is not generic but instead operates with python objects.
EDIT: In response to you comment ("error: ‘init’ was not declared in this scope"), I think the problem is that you are only including one Boost.Python header. Either #include <boost/python.hpp> or include all other parts that you need (one is init.hpp).
I have a custom container which I want to use in a ranged-based for loop. The container is somewhat based on a vector, like this:
template<typename T>
class IDMap
{
private:
struct Item {
uint16_t mVersion;
T mItem;
template <typename... Arguments>
Item(uint16_t version, Arguments&&... args) : mVersion(version), mItem(args...)
{
}
};
public:
typedef uint32_t ItemID;
template <typename... Arguments>
ItemID AddItem(Arguments&&... args);
void MarkAsFree(const ItemID id);
T& GetItem(const ItemID id);
T* TryGetItem(const ItemID id);
void Clear();
private:
std::vector<Item> mItems;
std::vector<uint16_t> mFreeIndices;
};
I want to iterate the mItems vector, but only return the mItem member rather than the entire Item struct. Is there any easy/elegant way to do this?
You have to provide a begin and end function, both returning a corresponding iterator, which itself implements operators ++, != and *. The begin and end functions can be free-standing or as members.
Start with implementing an iterator which has the behavior you want. You can implement it as a wrapper around a std::vector::iterator to save most of the "core" work.
The following is untested code
Basically, inside class IDMap, add:
class ItemIterator {
// based on vector iterator
std::vector<Item>::iterator i;
public:
ItemIterator(std::vector<Item>::iterator i) : i(i) {}
// incrementing
ItemIterator & operator ++() { ++i; return *this; }
ItemIterator operator ++(int) { const_iterator old(*this); ++(*this); return old; }
// comparison
bool operator!=(const ItemIterator &o) const { return i != o.i; }
// dereferencing
const T & operator*() const { return i->mItem; }
};
using iterator = ItemIterator;
using value_type = T;
ItemIterator begin() const { return ItemIterator(mItems.begin()); }
ItemIterator end() const { return ItemIterator(mItems.end() ); }
If you ever want to support multiple kinds of "special iteration" over your IDMap, like for example also over the indices, or over the "whole" Items, you should wrap everything above in another adaptor. This adaptor can then be accessed with a member method, like .items().
Brief example:
class IDMap {
// (your code)
public:
struct ItemsAdaptor {
// (insert above iterator definition + usings)
ItemsAdaptor(std::vector<Item>::iterator b,
std::vector<Item>::iterator e)
: b{b}, e{e}
{}
ItemIterator begin() const { return b; }
ItemIterator end() const { return e; }
private:
ItemIterator b, e;
};
ItemsAdaptor items() const {
return ItemsAdaptor(mItems.begin(), mItems.end());
}
};
Then, you can write:
IDMap<int> map = ...;
for (int i : map.items()) {
...
}
If you want the range-based for to work for your container, you have to provide begin and end functions that return forward iterators.
typedef std::vector<Item>::iterator iterator;
typedef std::vector<Item>::const_iterator const_iterator;
iterator begin()
{
return mItems.begin();
}
const_iterator begin() const;
{
return mItems.begin();
}
//also add end functions, and viola.
This will return the whole item struct. If you have to only return mItem, you'll have to write your own iterator adaptor and use it instead of vector's.
The premise
Say I have a container class Box which provides inner classes const_iterator and iterator. Because I want an iterator to be castable to a const_iterator, the latter inherits from the former:
class Box {
// ...
public:
class const_iterator : public std::iterator<std::random_access_iterator_tag, const int> { /* ... */ };
class iterator : public const_iterator { /* ... */ };
// ...
};
The problem
Now I want to test these classes using Google Test. Let's assert that the begin() and end() don't return the same thing:
const Box a;
EXPECT_NE(a.begin(), a.end());
Say hello to a compile error:
clang: no member named 'begin' in 'Box::const_iterator'
g++: ‘const class Box::const_iterator’ has no member named ‘begin’
The cause
Some research led me to this template in the Google Test source code (follow the link for expanded documentation):
typedef int IsContainer;
template <class C>
IsContainer IsContainerTest(int /* dummy */,
typename C::iterator* /* it */ = NULL,
typename C::const_iterator* /* const_it */ = NULL) {
return 0;
}
The result of this template magic is that if arguments to EXPECT_* have iterator and const_iterator member classes, then the type is assumed to be a container class. Knowing this, Google Test can print pretty human-readable reports when expectations fail, which is nice.
However, there's this little detail:
// Note that we look for both C::iterator and C::const_iterator. The
// reason is that C++ injects the name of a class as a member of the
// class itself (e.g. you can refer to class iterator as either
// 'iterator' or 'iterator::iterator'). If we look for C::iterator
// only, for example, we would mistakenly think that a class named
// iterator is an STL container.
so if I understand things right, this means that
Box::const_iterator has itself as a member class named const_iterator, and std::iterator as a memberclass named iterator.
Box::iterator has itself as a member class named iterator and Box::const_iterator as a member class named const_iterator.
Therefore both my iterator classes look like container classes to Google Test!
The question
How do I design my iterator classes to make them not look like containers?
Things I've tried:
Declaring the std::iterator superclass of const_iterator as private. This solves the problem for const_iterator by hiding the iterator member class, but it still doesn't let me pass a.begin() as a parameter to EXPECT_NE unless a is const. Seems like Google Test uses iterator begin() rather than const_iterator begin() const for some reason.
Removing the std::iterator superclass altogether. Is this a bad idea? I suppose I'll have to declare my std::iterator_traits manually, is there anything else I'll lose by not extending std::iterator?
Declaring the Box::const_iterator superclass of Box::iterator as private. This may or may not be an option since I'd have to redeclare methods I'd rather want to reuse (such as operator++).
Is there anything else I've overlooked?
The example
#include<iterator>
#include <memory> //unique_ptr<T>
#include <gtest/gtest.h>
class ThreeInts {
std::unique_ptr<int[]> v;
public:
ThreeInts() : v(new int[3]) { v[0] = 0; v[1] = 1; v[2] = 2; };
ThreeInts(int val) : ThreeInts() { v[0] = val; v[1] = val; v[2] = val; };
bool operator==(const ThreeInts& other) const {
return v[0] == other.v[0] && v[1] == other.v[1] && v[2] == other.v[2];
}
class const_iterator : public std::iterator<std::random_access_iterator_tag, const int> {
protected:
int* p;
public:
explicit const_iterator(int* p) : p(p) {}
const_iterator& operator++() { ++p; return *this; }
bool operator==(const const_iterator& rhs) const { return p == rhs.p; }
bool operator!=(const const_iterator& rhs) const { return p != rhs.p; }
int operator*() const { return *p; }
};
class iterator : public const_iterator {
public:
explicit iterator(int* p) : const_iterator(p) {}
int& operator*() const { return *p; }
};
iterator begin() { return iterator(v.get()); }
iterator end() { return iterator(v.get()+3); }
const_iterator begin() const { return const_iterator(v.get()); }
const_iterator end() const { return const_iterator(v.get()+3); }
};
TEST(ThreeInts, ThisTestCompilesAndPrettyFailureMessagesAreShown) {
const ThreeInts a(1), b(2);
ThreeInts c(1), d(2);
EXPECT_EQ(a, b);
EXPECT_EQ(a, c);
EXPECT_EQ(c, d);
}
TEST(ThreeInts, ThisTestCompilesIfTheStdIteratorParentIsPrivate) {
const ThreeInts a;
EXPECT_NE(a.begin(), a.end());
}
TEST(ThreeInts, ThisTestAlsoCompilesIfTheStdIteratorParentIsPrivateButItIsAHassle) {
ThreeInts a;
ThreeInts::const_iterator beg = a.begin();
ThreeInts::const_iterator end = a.end();
//EXPECT_NE(beg, end); // Compile error unless the std::iterator superclass is private
}
TEST(ThreeInts, ThisTestDoesNotCompileEvenIfTheStdIteratorParentIsPrivate) {
ThreeInts a;
//EXPECT_NE(a.begin(), a.end());
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
ThreeInts::iterator should not inherit from ThreeInts::const_iterator, instead they should be implemented separately.
class ThreeInts::iterator : public std::iterator< std::random_access_iterator_tag, int> { ... }
class ThreeInts::const_iterator : public std::iterator< std::random_access_iterator_tag, const int> { ... }
The problem seems to be that otherwise ThreeInts::const_iterator both has members named const_iterator and iterator (aka the constructors). Also making the iterator inherit from const_iterator is not const-correct as the const_iterator should only hold a pointer/similar to const data. STL containers also keep the two iterators separate.
In that code, it would probably be sufficient to instead of defining iterator classes, simply define
using iterator = int*;
using const_iterator = const int*;
I am porting this code from Visual C++ 6.0 (it also worked with an older GCC++) to Visual Studio 2010 C++. The code compiles but throws an exception.
I have an base class, CncMatchedQueryAtom. This class is used contain matches of different types of target atoms (this is a graph matching application) for 99% of the cases there is a one to one match between the query and the target. This is handled by the derived class, CncMatchedQueryAtomSimple. This class works great. The problem is that some query atoms match groups of atoms, this is handled by the class, CncMatchedQueryAtomGroup. This class contains a vector with the matched atoms. I want the iterator class defined within the base class to encapsulate the vector iterator in the derived class such that begin() returns the vector begin() and the end returns the vector's end().
The old version has problems on the end() at runtime because it does the conversion by:
return &*group.end();
Which is no longer allowed by Visual C++
So how can a base class specify an iterator that derived classes can implement? This doesn't seem very obvious to me, but I'm new to C++. Nor is it something that seasoned C++ developers that I work with know of either.
Basically, I want the base class to have methods that provide begin and end functions that the derived classes implement.
Here is the code:
class CncMatchedQueryAtom
{
protected:
int notBlockAllocated;
public:
int allocateIndividually() const
{
return notBlockAllocated;
}
const CncAtom *queryAtom;
CncAtom *queryAtomVolitile() const
{
return (CncAtom*)queryAtom;
}
// set when the class has been allocated by newing
// intialize all default constructors to be notBlockAllocated
CncMatchedQueryAtom()
: notBlockAllocated(1)
, queryAtom(NULL) // i don't think this needs to be initialized to null
{
}
CncMatchedQueryAtom(int noBlock)
: notBlockAllocated(noBlock)
, queryAtom(NULL) // i don't think this needs to be initialized to null
{
}
// may not need this now that it's a virtual!
CncMatchedQueryAtom(const CncMatchedQueryAtom &that)
: queryAtom(NULL)
{
*this = that;
}
// this needs to be virtual so when delete CncMatchedQueryAtom is called
// the virtual calss members are destructed too
virtual ~CncMatchedQueryAtom()
{
}
virtual void dump() const =0;
virtual void clearMapping() =0;
virtual CncMatchedQueryAtom *newCopy() const =0;
virtual void coverHits(class CncTarget *) const = 0;
// iterates over all matched target atoms for this query atom
class iterator
{
private:
CncMatchedTargetAtom *ptr;
public:
iterator()
{
}
iterator(const CncMatchedTargetAtom *targetAtom) // constructor from a target ptr
:ptr((CncMatchedTargetAtom *)targetAtom)
{
}
iterator(const iterator &oldOne)
:ptr(oldOne.ptr)
{
}
~iterator()
{
}
int operator==(const iterator &that) const
{
return ptr==that.ptr;
}
int operator!=(const iterator &that) const
{
return ptr!=that.ptr;
}
const CncMatchedTargetAtom &operator*() const
{
return *ptr;
}
iterator operator++(int NotUsed) // post increment
{
iterator returnValue(*this);
++ptr;
return returnValue;
}
iterator &operator++() // pre increment
{
++ptr;
return *this;
}
int operator<(const iterator &rhs) const
{
return (this->ptr < rhs.ptr);
}
CncMatchedTargetAtom *operator->()
{
return ptr;
}
};
virtual iterator begin() const =0;
virtual iterator end() const =0;
virtual int size() const = 0;
virtual double molecularWeight() const = 0;
const CncAtom *getFirstTargetAtom() const
{
return (*begin()).matchedTargetAtom;
}
CncAtom *getFirstTargetAtomVolitile() const
{
return (CncAtom*)getFirstTargetAtom();
}
}; // class CncMatchedQueryAtom
class CncMatchedQueryAtomSimple : public CncMatchedQueryAtom
{
public:
// we need a constructor here since this is allocated with blockAlloc
CncMatchedQueryAtomSimple()
: CncMatchedQueryAtom(0)
{
}
// we use simple.targetAtom as a temporary variable
// used to pass to matching functions
CncMatchedTargetAtom simple;
void clearIt()
{
queryAtom=NULL;
notBlockAllocated=0;
}
// if queryAtom is an element-type atom (or Lp or A atom)
void dump() const;
void clearMapping()
{
}
CncMatchedQueryAtom *newCopy() const
{
// since this is usually not allocatedIndividually I'll set
// the notBlockAllocatedFlag on the copy to be sure if this
// does happen it will individually deallocate it
CncMatchedQueryAtomSimple *retVal = new CncMatchedQueryAtomSimple(*this);
retVal->notBlockAllocated = 1;
return (CncMatchedQueryAtom *)retVal;
}
void coverHits(class CncTarget *) const;
iterator begin() const
{
return &simple;
}
iterator end() const
{
return &simple+1;
}
int size() const
{
return 1;
}
double molecularWeight() const
{
return CncMolGetAtomicMassAve(simple.matchedTargetAtom->getAtomicNumber());
}
}; // class CncMatchedQueryAtomSimple
class CncMatchedQueryAtomGroup : public CncMatchedQueryAtom
{
public:
// if queryAtom is an R- or X-group searching for
std::vector<CncMatchedTargetAtom> group;
void dump() const;
void clearMapping()
{
group.clear();
}
CncMatchedQueryAtom *newCopy() const
{
return new CncMatchedQueryAtomGroup(*this);
}
void coverHits(class CncTarget *) const;
iterator begin() const
{
return &*group.begin();
}
iterator end() const
{
// this is a hack, works with Visual C++ 6.0 and older GCC++ but not VS C++ 2010
return &*group.end(); // Throws error at runtime! Iterator Not Dereferencable
}
int size() const
{
return group.size();
}
double molecularWeight() const
{
double sum=0;
std::vector<CncMatchedTargetAtom>::const_iterator q;
for (q=group.begin()
; q!=group.end()
; ++q)
{
sum += CncMolGetAtomicMassAve(q->matchedTargetAtom->getAtomicNumber());
}
return sum;
}
}; // class CncMatchedQueryAtom
An example of how the iterator is called:
// Sample call to the iterator
// (*elem)->getMatchedAtom() returns a CncMatchedQueryAtom *
CncMatchedQueryAtom::iterator atomMatched;
// welp it looks like we have to do these
//(*elem)->getFirstTargetAtom
for (atomMatched=(*elem)->getMatchedAtom()->begin()
; atomMatched!=(*elem)->getMatchedAtom()->end() // Runtime exception here!
; ++atomMatched)
{
existenceFingerprint.setBit(
atomMatched->matchedTargetAtom->indexInStructure);
}
Thanks, hopefully this isn't too much code...
You cannot convert iterators from one container into iterators to another container.
It used to work with VC6, because they happened to use a pointer as vector::iterator. Later versions have an iterator class where the conversion does not work.