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).
Related
#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
Is there a way I could avoid using Range2 as a name and have both classes named Range? I'm a bit confused with the C++ template syntax.
template <int BEGIN, int END>
class Range2
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
template<int END>
class Range
: public Range2<0, END>
{
};
As with function arguments, in C++ template arguments can have a default value. The only thing you will have to pay for this putting the END, which has no default value, before the BEGIN, which has 0 as default.
// Here we add the default parameter to BEGIN
// The arguments are switched because END is without a default
// parameter, so it has to come before BEGIN that has one
template <int END, int BEGIN=0>
// The class itself is the same, but now you can use it
// without giving a BEGIN parameters
class Range
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
It compiles and should work as intended. Without a main, I wasn't able to test it, though.
EDIT: I added some comments and here an example of usage, just for clarity:
Range<10, 3> r(3); /*here we use it as usual, pay attention begin is
now the second argument and not the first */
Range<10> r(0); /* here we don't give a BEGIN argument, the
compiler will use the default one */
Updated
I am working on some container code in an environment where I the STL is not available to me. I am trying to generalize my iterators to reduce code duplication. I've encountered a case where I have a container that can contain Objects or pointers to Objects. I am having a compilation problem when trying to compile the following (contrived) code:
struct Object
{
};
template<typename Container, typename T>
struct IteratorBase
{
IteratorBase( Container * container, T curr ) : _container( container ), _curr( curr ) { }
Container * _container;
T _curr;
T & GetValue() const { return _curr; }
void Invalidate() { _curr = NULL; }
};
template<typename T>
struct Container
{
typedef typename T * Type;
typedef IteratorBase<Container<T>, Type> Iterator;
Iterator GetIterator() { return Iterator( this, storage ); }
T storage[10];
};
int main(int argc, char* argv[])
{
Container<Object> containerByAddress;
const Object* pA = containerByAddress.GetIterator().GetValue();
return 0;
}
The error is
error C2440: 'return' : cannot convert from 'Object *const ' to 'Object *&'
while compiling class template member function 'Object &IteratorBase<Container,T>::GetValue(void) const'
So I have made some changes to change how the value is returned by deducing the type of T using the following:
template<typename T>
struct DetermineReturnType
{
typedef T & ReturnType;
};
template<typename T>
struct DetermineReturnType<T*>
{
typedef T * ReturnType;
};
template<typename Container, typename T>
struct IteratorBase
{
IteratorBase( Container * container, T curr ) : _container( container ), _curr( curr ) { }
Container * _container;
T _curr;
typedef typename DetermineReturnType<T>::ReturnType ReturnType;
ReturnType GetValue() const { return _curr; }
void Invalidate() { _curr = NULL; }
};
Now my iterator uses & or * based on T.
But my question is - is this a reasonable solution? is there something I can do to fix this?
Please note I cannot use STL, Boost, nor latest version of C++ as this is an embedded system some years old.
Thanks for any insight.
The problem is that GetValue() is declared const but you are returning a non-const reference to a member variable. If the compiler allowed you do to this you would be able to modify the member variable in a possibly const qualified instance of the iterator. You can solve this pretty easily by providing both a const and non-const version of GetValue(). The compiler will choose the appropriate version based on the CV qualifiers of the iterator instance.
T const& GetValue() const { return _curr; }
T& GetValue() { return _curr; }
Unfortunately this is not likely going to get you the real behavior you are looking for. You really should not be returning a reference here as it will only allow you to change the element inside iterator rather than the element in the container. To get where you want you'll need to change more than just the GetValue implementation and redesign your iterators to work with the elements in the container rather than maintaining it locally.
Below is a basic example of how you might approach this. It returns a reference to the element in the container allowing you to modify the container through the iterator. Since I don't have a full version of your Container I'm using naked arrays but the visible end result should be easy to grasp.
#include <iostream>
struct Object { };
template<typename T>
struct IteratorBase
{
IteratorBase(T* initialPtr) : _curr(initialPtr) {}
T* _curr;
T const & GetValue() const { return *_curr; }
T& GetValue() { return *_curr; }
void next() { ++_curr; }
void prev() { --_curr; }
};
int main()
{
Object a, b, c, d, e;
Object *objects[] = { &a, &b, &c, &d, &e };
IteratorBase<Object*> it(objects);
for (int i = 0; i < sizeof(objects) / sizeof(*objects); i++)
{
std::cout << it.GetValue() << "\n";
it.GetValue() = NULL;
it.next();
}
it = IteratorBase<Object*>(objects);
for (int i = 0; i < sizeof(objects) / sizeof(*objects); i++)
{
std::cout << it.GetValue() << "\n";
it.next();
}
}
I have a hash table template that I have written for a class. I have a project due that relies on utilizing this hash table. It accepts an unsigned integer value to initialize the number of buckets it has, as well as a hash function to point to. I have not written that hash function yet, but I have a declaration for it. When I try to use the member initializer in my Game class for the hash table data member, it gives me an error that I don't understand.
Error 1 error C3867: 'Game::xorHash': function call missing argument list; use '&Game::xorHash' to create a pointer to member
2 IntelliSense: no instance of constructor "HTable<Type>::HTable [with Type=std::string]" matches the argument list
argument types are: (int, unsigned int (const std::string &s))
my Hash Table class is as follows:
#pragma once
#include "SLList.h"
template<typename Type> class HTable
{
public:
HTable(unsigned int numOfBuckets, unsigned int (*hFunction) (const Type &v));
~HTable();
HTable<Type>& operator=(const HTable<Type>& that);
HTable(const HTable<Type>& that);
void insert(const Type& v);
bool findAndRemove(const Type& v);
void clear();
int find(const Type& v) const;
private:
SLList<Type>* ht;
unsigned int (*hFunct) (const Type &v);
unsigned int numOfBuck;
};
template<typename Type>
HTable<Type>::HTable(unsigned int numOfBuckets, unsigned int (*hFunction) (const Type &v))
{
ht = new SLList<Type>[numOfBuckets];
this->numOfBuck = numOfBuckets;
this->hFunct = hFunction;
}
template<typename Type>
HTable<Type>::~HTable()
{
delete [] ht;
ht = nullptr;
}
template<typename Type>
HTable<Type>& HTable<Type>::operator=(const HTable<Type>& that)
{
if(this != &that)
{
delete [] this->ht;
this->hFunct = that.hFunct;
this->numOfBuck = that.numOfBuck;
this->ht = new SLList<Type>[numOfBuck];
for(unsigned int i = 0; i < this->numOfBuck; i++)
this->ht[i] = that.ht[i];
}
return *this;
}
template<typename Type>
HTable<Type>::HTable(const HTable<Type>& that)
{
this = *that;
}
template<typename Type>
void HTable<Type>::insert(const Type& v)
{
ht[hFunct(v)].addHead(v);
}
template<typename Type>
bool HTable<Type>::findAndRemove(const Type& v)
{
SLLIter<Type> iter(ht[hFunct(v)]);
for(iter.begin(); !iter.end(); ++iter)
{
if(v == iter.current())
{
ht[hFunct(v)].remove(iter);
return true;
}
}
return false;
}
template<typename Type>
void HTable<Type>::clear()
{
for(unsigned int i = 0; i < this->numOfBuck; ++i)
ht[i].clear();
}
template<typename Type>
int HTable<Type>::find(const Type& v) const
{
SLLIter<Type> iter(ht[hFunct(v)]);
for(iter.begin(); !iter.end(); ++iter)
{
if(v == iter.current())
return hFunct(v);
}
return -1;
}
My Game.h:
#pragma once
#include "stdafx.h"
#include "HTable.h"
#include "BST.h"
#include "DTSTimer.h"
using namespace std;
class Game
{
public:
Game(void);
virtual ~Game(void);
void refresh();
void input();
unsigned int xorHash(const string &s);
private:
string userInput;
DTSTimer timer;
BST<string> answers;
HTable<string> dictionary;
};
My Game.cpp (this is obviously just a skeleton, since I can't get the member init to work)
#include "Game.h"
Game::Game(void) : dictionary(2048, xorHash)
{
}
Game::~Game(void)
{
}
void Game::refresh()
{
}
void Game::input()
{
}
unsigned int Game::xorHash(const string &s)
{
return 0;
}
I've been working on this for a good while, and have been hitting a wall. I would really appreciate some help on how to get this thing up and running. Let me know if there is another snippet that needs to be seen (I've tried to be thorough in that regard).
You have two problems. The first is that you don't pass the member function pointer properly (the error message tells you exactly what do do). The other problem is that a function pointer is not the same as a member function pointer.
A member function pointer needs an instance object object to call the member function on. And this instance is passed as a hidden first argument, something that normal functions don't have.
For this you might instead turn to std::function and std::bind:
class HTable
{
public:
HTable(unsigned int numOfBuckets, std::function<unsigned int(const Type&)> hFunction);
...
private:
std::function<unsigned int(const Type&)> hFunct;
...
};
Then
Game::Game(void) : dictionary(2048, std::bind(&Game::xorHash, this))
{
}
I need to create a generic object carrier class. I came up with something simple like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
This works well when T has got a default constructor (parameterless). Things gets complicated when T has parameterized constructors. So I rewrote the class like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return *item_;
}
void setItem(T& item)
{
item_ = new T ( item );
}
private:
T* item_;
};
Changed the item_ variable to T* and created a new instance using the copy constructor of T. Again this worked well until T is a pointer type. I mean ObjectCarrier<Foo*> won't work.
I am wondering how can I design this class so that it works for almost all kind of types. I think I may need to create a traits type specialized for pointers. But unfortunately, I am not able to make that work.
Any help would be great.
The above approaches are way way too complicated. Keep it simple, and just solve the constructor arg problem by using template constructors. Don't use pointers, they will create object lifetime and copying headaches.
Here's an implementation I use a lot. The template constructors will forward arguments for things directly on to the nested object which is convenient. The operator T& values let you pass carrier<T> to functions that take a type T, without expensive copying. You can wrap objects that take up to two arguments with this code.
/* A wrapper of type T */
template <typename T>
struct carrier {
carrier() {}
template <typename A1> carrier(const A1& a1) : value(a1) {}
template <typename A1, typename A2> carrier(const A1& a1, const A2& a2) : value(a1, a2) {}
operator T&() { return value; }
operator const T&() const { return value; }
T value;
};
You can use it like this:
const carrier<point> p1(10,10); // make p1 const to stop people changing it
showPoint(p1); // calls a function that expects a point,
showPoint(p1.value); // access the point directly
You can use template specialization for the T* type and rewrite the methods to suite pointers. You can do something like:
template<typename T>
class ObjectCarrier<T*>
{
public:
const T* item() const
{
return item_;
}
void setItem(T* item)
{
item_ = item;
}
private:
T* item_;
};
There is a design patern that is possibly relevant to this - Memento.
A bit off topic, but bear in mind that as soon as you start newing objects up inside your class, you'll need a way to manage the memory. I'd suggest using an std::auto_ptr at the least. You'll also need to provide a copy constructor and an assignment operator, when using std::auto_ptr.
It might be possible to hold the object by value and still defer its construction with the use of placement new and something like the following:
#include <iostream>
#include <cassert>
template <class T>
class ObjectCarrier
{
public:
ObjectCarrier(): ref(0) {}
ObjectCarrier(const ObjectCarrier& other): ref(0)
{
set_data(other.ref);
}
~ObjectCarrier()
{
clear();
}
const ObjectCarrier& operator = (const ObjectCarrier& other)
{
if (other.empty())
clear();
else
set_data(other.ref);
return *this;
}
void set(const T& value)
{
set_value(value);
}
const T& get() const
{
assert(!empty() && "No object being carried");
return *ref;
}
bool empty() const
{
return ref == 0;
}
void clear()
{
if (!empty()) {
ref->~T();
ref = 0;
}
}
private:
char data[sizeof(T)];
T* ref;
void set_value(const T& value)
{
if (!empty()) {
*ref = value;
}
else {
ref = new (data) T(value);
}
}
void set_data(const T* value)
{
if (value) {
set_value(*value);
}
}
};
int main()
{
ObjectCarrier<int> i;
ObjectCarrier<int> j(i);
i = j;
i.set(10);
std::cout << i.get() << '\n';
j = i;
i.set(20);
std::cout << i.get() << ' ' << j.get() << ' ' << ObjectCarrier<int>(i).get() << '\n';
}
However, I would somewhat question the usefulness of this class. Perhaps the only purpose it could have, would be to act as Boost.Optional.
But if you don't want the class to be able to not hold a value, just give it a parametrized constructor:
template<typename T>
class ObjectCarrier
{
public:
ObjectCarrier(const T& value = T()):
item_(value)
{
}
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
(It's just that this class seems rather useless, unless perhaps as a facade for code that expects variables to have item and setItem methods, rather than, say, an assignment operator.)
boost::optional does something very similar to this (also boost::any, but nevermind).
You can check out how its implemented at: http://cplusplus.co.il/2009/12/04/boost-optional-and-its-internals/ and don't worry - it's pretty straightforward.