Here is my insert method of a chaining class that I implement, the data type is integer (typedef int TELEM).By displaying the numbers stored, from 16 shows me other values too big
include
typedef int TELEM;
// liste d'éléments de type TELEM
class liste {
public:
liste::liste() : m_nb(0) ,m_tetefile(0)
{
m_tetefile = new TELEM[m_nb+1] ;
}
liste::~liste()
{
m_nb = 0;
delete m_tetefile;
}
bool liste::est_vide() const
{
return m_nb == 0;
}
int liste::taille() const
{
return m_nb;
}
const TELEM& liste::operator[](int i) const
{
assert((i>=1) && (i<=m_nb));
return (m_tetefile[i]);
}
void liste::inserer(const TELEM& e, int i)
{
assert((i>=1) && (i<=m_nb+1));
for (int k = m_nb ; k >= i ; --k)
m_tetefile[k+1] = m_tetefile[k];
m_tetefile[i] = e;
std::cout << e <<std::endl;
std::cout << m_tetefile[i] <<std::endl;
m_nb++;
}
private:
TELEM m_nb ;
TELEM *m_tetefile;
};
std::ostream& operator<<(std::ostream& os, const liste& l)
{
os << '(';
if (!l.est_vide())
os << l[1];
for (int i=2; i<=l.taille(); ++i)
os << ',' << l[i];
os << ')';
return os;
}
from 16 ca gives me this
(2,4,6,8,10,12,14,875311656,942421548,741355820)
instead
(2,4,6,8,10,12,14,16,18,20)
I am trying to implement a vector using my own class so I can not do the initialiser list part
# include <iostream>
# include <exception>
# include<initializer_list>
template <class T>
class vector {
public:
T* a;
T n;
int pos, c;
vector() { a = 0; n = 0; }
vector(T n) : n(n) { a = new T[n]; }
vector(std::initializer_list <vector> l) {
a = new T[int(sizeof(l))];
for (int f : l)
*(a + f) = l.begin() + f;
}
void push_back(T k) {
int i = k;
*(a + n) = k;
}
vector& operator= (vector&& th) {
this->a = th.a;
th.a = nullptr; return (*this);
}
vector& operator=(vector& k)
{
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
I am just trying to use pointer offset notation to take the initializer list items into the dynamic array but I get errors VS 17 IDE
Severity Code Description Project File Line Suppression
Error C2440 '=': cannot convert from 'const _Elem *' to 'T'
Error C2440 'initializing': cannot convert from 'const _Elem' to 'int'
Hello Nimrod!
#include <iostream>
#include <exception>
#include <initializer_list>
// normally people don't place a space between '#' and 'include'
template <class T>
class vector {
public:
T* a;
int n;
// probably it is length the vector
// change T to int
int pos, c;
vector() {
a = nullptr;
// do not use '0' to instruct null pointer
n = 0;
}
vector(int n): n(n) { a = new T[n]; }
vector(std::initializer_list<T> l) {
a = new T[l.size()];
// redundant force cast from size_t to int
for (int i = 0; i < l.size(); i++) {
a[i] = l.begin()[i];
}
// for (int f : l) # it seems that you wrote JavaScript before?
// *(a + f) = l.begin() + f;
}
void push_back(T k) {
// assigns "T k" to "int i"? it's confusing
// int i = k;
// *(a + n) = k;
}
// probably still many problems
vector& operator=(vector&& th) {
this->a = th.a;
th.a = nullptr;
return (*this);
}
vector& operator=(vector& k) {
this->a = k.a;
return(*this);
}
int size() { return n; }
void pop_back() { *(a + n) = nullptr;
n--;
}
void resize(int c) {
delete a;
n = c;
a = new T[c];
}
T operator[](int pos) {
if (pos > sizeof(a))
std::cout << "out of range";
else return *(a + pos);
}
};
int main() {
vector<int> a(10);
vector<char>b{ 'w','b','f','g' };
getchar();
return 0;
}
You still need more practice. XP
In your context of code, template variable for initializer_list should be T rather than int.
Range for loop with initializer_list<T> will fetch the values
in the list. Therefore it should belong to T.
Custom lambda Comparator slower than normal function c++11. I experienced this a few times. But, Still Couldn't figure out the reason why this is so. Does anyone experience this and know the cause behind it?
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 1;
vector<int> v(N);
vector<int> sorted(N);
map<int, int> counts;
long long start;
void startClock() {
start = clock();
}
void stopClock() {
cout << float( clock () - start ) / CLOCKS_PER_SEC << endl;
}
void copyOriginal() {
for (int i = 0; i < N; ++i)
sorted[i] = v[i];
}
void sortWLambda(map<int, int>& counts) {
cout << "sorting with lambda" << endl;
sort(sorted.begin(), sorted.end(), [counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
}
bool comparator(const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
}
void sortWoLambda() {
cout << "sorting w/o lambda" << endl;
sort(sorted.begin(), sorted.end(), comparator);
}
int main() {
for (int i = 0; i < N; ++i) {
int num = rand() % 1234;
counts[num]++;
v[i] = num;
}
copyOriginal();
startClock();
sortWLambda(counts);
stopClock();
copyOriginal();
startClock();
sortWoLambda();
stopClock();
return 0;
}
sorting with lambda 6.28 sec
sorting w/o lambda 0.17 sec
pass by reference made the difference for lambda.
I tried this..
sort(sorted.begin(), sorted.end(), [&counts](const int& a, const int& b) {
if (*counts.find(a) != *counts.find(b)) return *counts.find(a) < *counts.find(b);
return a < b;
});
now this takes same time as normal function
Passing by constant reference in the lambda capture list this helped me too!
How to implement a random access iterator for a sequence of elements which less than a single byte? For example, 6 bits.
Code example to illustrate what I want:
template<typename T>
class val_iterator : std::iterator<std::random_access_iterator_tag, T>
{
// ???
};
template<typename T>
class val_container
{
void *_data;
public:
val_container(void *data): _data(data) {}
// ???
};
int main()
{
std::vector<unsigned int> vec =
{
0xA, // '00 1010'
0xE, // '00 1110'
0x1F,// '01 1111'
0x3F // '11 1111'
};
// 4 elements of 6 bits
const size_t byte_count = 4 * 6 / 8;
std::array<unsigned char, byte_count> bytes;
val_container<unsigned char> values(bytes.data());
val_iterator<unsigned char> val_it = values.begin();
for(auto it = vec.begin(); it != vec.end(); ++it, ++val_it)
*val_it = (unsigned char) *it;
// elements:
// '00 1010'_'00 1110'_'01 1111'_'11 1111'
// bytes in memory:
// '0010 1000'_'1110 0111'_'1111 1111'
assert(bytes[0] == 0x28); // '0010 1000'
assert(bytes[1] == 0xE7); // '1110 0111'
assert(bytes[1] == 0xFF); // '1111 1111'
assert(values[0] == 0xA); // '00 1010'
assert(values[1] == 0xE); // '00 1110'
assert(values[2] == 0x1F); // '01 1111'
assert(values[3] == 0x3F); // '11 1111'
return 0;
}
Or it is not random access iterator, but another category of iterators?
I also think that this byte sequence consists of repeating blocks of three bytes each, which store 4 elements each. Maybe it knowledge can be used in an iterator, but I don't know how, yet.
EDIT:
I was not right about the location of bits in the byte array. In little-endian bits will looks like this: image
And, I try to implement this iterator/container. I used this code for start, and implementation of std::vector<bool> to write reference of value.
template<size_t TBitCount, typename TDataType, typename TValueType>
struct val_help
{
static size_t vals_count_in_block;
static size_t bytes_count_in_block;
static TValueType max_value;
static bool init()
{
static bool inited = false;
if(inited)
return true;
constexpr size_t value_size_in_bits = sizeof(TValueType) * 8;
static_assert(TBitCount >= 1, "TBitCount must be at least 1 bit");
static_assert(TBitCount <= value_size_in_bits, "TValueType doesn't have enough bit");
static_assert(sizeof(TDataType) == 1, "sizeof TDataType must be 1 byte");
size_t bits = 0;
size_t data_size_in_bits = sizeof(TDataType) * 8;
do {
vals_count_in_block++;
bits += TBitCount;
} while (bits % data_size_in_bits != 0);
bytes_count_in_block = bits / 8;
inited = true;
return true;
}
static size_t get_byte_idx(size_t val_idx)
{
return val_idx * bytes_count_in_block / vals_count_in_block;
}
static size_t get_lo_shift(size_t val_idx)
{
return (val_idx * TBitCount) % 8;
}
};
template<size_t TBitCount, typename TDataType, typename TValueType>
size_t val_help<TBitCount, TDataType, TValueType>::vals_count_in_block = 0;
template<size_t TBitCount, typename TDataType, typename TValueType>
size_t val_help<TBitCount, TDataType, TValueType>::bytes_count_in_block = 0;
template<size_t TBitCount, typename TDataType, typename TValueType>
TValueType val_help<TBitCount, TDataType, TValueType>::max_value = (1 << TBitCount) - 1;
template<size_t TBitCount, typename TDataType, typename TValueType>
class val_reference
{
using h = val_help<TBitCount, TDataType, TValueType>;
TDataType* _data;
size_t _val_idx;
public:
val_reference() : _data(nullptr), _val_idx(0) {}
val_reference(TDataType* data, size_t val_idx) : _data(data), _val_idx(val_idx) {}
operator TValueType() const
{ return get_value(); }
val_reference& operator=(TValueType val)
{
set_value(val);
return *this;
}
val_reference& operator=(const val_reference rhs) const
{ return *this = TValueType(rhs); }
bool operator==(const val_reference rhs) const
{ return TValueType(*this) == TValueType(rhs); }
bool operator<(const val_reference rhs) const
{ return TValueType(*this) < TValueType(rhs); }
// ToDo other operation
size_t idx() const
{ return _val_idx; }
private:
TValueType get_value() const
{
size_t byte_idx = h::get_byte_idx(_val_idx);
auto ptr_to_val = reinterpret_cast<TValueType*>(_data + byte_idx);
size_t lo_shift = h::get_lo_shift(_val_idx);
size_t hi_shift = sizeof(TValueType) * 8 - lo_shift;
bool is_hi_valid = byte_idx + sizeof(TValueType) < h::bytes_count_in_block;
auto lo = *ptr_to_val >> lo_shift;
auto hi = is_hi_valid ? *(ptr_to_val + 1) << hi_shift : 0;
return (hi | lo) & h::max_value;
}
void set_value(TValueType value)
{
auto val = value & h::max_value;
size_t byte_idx = h::get_byte_idx(_val_idx);
auto ptr_to_val = reinterpret_cast<TValueType*>(_data + byte_idx);
size_t lo_shift = h::get_lo_shift(_val_idx);
size_t hi_shift = sizeof(TValueType) * 8 - lo_shift;
TValueType &lo = *ptr_to_val;
lo = (lo & ~(h::max_value << lo_shift)) | (val << lo_shift);
bool is_hi_valid = byte_idx + sizeof(TValueType) < h::bytes_count_in_block;
if(is_hi_valid)
{
TValueType &hi = *(ptr_to_val + 1);
hi = (hi & ~(h::max_value >> hi_shift)) | (val >> hi_shift);
}
}
};
template<size_t TBitCount, typename TDataType, typename TValueType>
class val_iterator : public std::iterator<std::random_access_iterator_tag, TValueType>
{
using h = val_help<TBitCount, TDataType, TValueType>;
TDataType *_data;
size_t _val_idx;
public:
using reference = val_reference<TBitCount, TDataType, TValueType>;
using pointer = val_reference<TBitCount, TDataType, TValueType>*;
using iterator = val_iterator<TBitCount, TDataType, TValueType>;
using difference_type = int;
val_iterator(TDataType* data) : _data(data), _val_idx(0){}
val_iterator(TDataType* data, unsigned int val_idx) : _data(data), _val_idx(val_idx){}
val_iterator(const iterator& rhs) : _data(rhs._data), _val_idx(rhs._val_idx) {}
iterator& operator=(const iterator& rhs)
{
_data = rhs._data;
_val_idx = rhs._val_idx;
return *this;
}
reference operator*() const
{ return reference(_data, _val_idx); }
reference operator[](const difference_type& n) const
{ return *(*this + n); }
iterator& operator++()
{
if(_val_idx == h::vals_count_in_block - 1)
{
_data += h::bytes_count_in_block;
_val_idx = 0;
}
else
{
++_val_idx;
}
return *this;
}
iterator& operator--()
{
if(_val_idx == 0)
{
_data -= h::bytes_count_in_block;
_val_idx = h::vals_count_in_block - 1;
}
else
{
--_val_idx;
}
return *this;
}
iterator operator++(int)
{
iterator tmp(*this);
++(*this);
return tmp;
}
iterator operator--(int)
{
iterator tmp(*this);
--(*this);
return tmp;
}
iterator& operator+=(const difference_type& n)
{
auto idx = _val_idx + n;
_data += (idx / h::vals_count_in_block) * h::bytes_count_in_block;
_val_idx = idx % h::vals_count_in_block;
return *this;
}
iterator operator+(const difference_type& n) const
{
iterator tmp(*this);
tmp += n;
return tmp;
}
iterator& operator-=(const difference_type& n)
{
if(n <= _val_idx)
{
_val_idx -= n;
return *this;
}
auto diff_idx = (n % h::vals_count_in_block) - _val_idx;
auto idx = n - diff_idx;
_data -= (idx / h::vals_count_in_block + 1) * h::bytes_count_in_block;
_val_idx = h::vals_count_in_block - diff_idx;
return *this;
}
iterator operator-(const difference_type& n) const
{
iterator tmp(*this);
tmp -= n;
return tmp;
}
bool operator==(const iterator& rhs) const
{
return _data == rhs._data && _val_idx == rhs._val_idx;
}
bool operator!=(const iterator& rhs) const
{
return !(*this == rhs);
}
bool operator<(const iterator& rhs) const
{
return _data == rhs._data
? _val_idx < rhs._val_idx
: _data < rhs._data;
}
bool operator<=(const iterator& rhs) const
{
return *this < rhs || *this == rhs;
}
bool operator>(const iterator& rhs) const
{
return !(*this <= rhs);
}
bool operator>=(const iterator& rhs) const
{
return !(*this < rhs);
}
};
template<size_t TBitCount, typename TDataType, typename TValueType,
typename std::enable_if<std::is_integral<TValueType>::value, int>::type = 0>
class val_container
{
using h = val_help<TBitCount, TDataType, TValueType>;
TDataType* _data;
size_t _size;
public:
using value_type = TValueType;
using size_type = size_t;
using difference_type = int;
using reference = val_reference<TBitCount, TDataType, TValueType>;
using const_reference = TValueType;
using pointer = val_reference<TBitCount, TDataType, TValueType>*;
using const_pointer = const TValueType*;
using iterator = val_iterator<TBitCount, TDataType, TValueType>;
using const_iterator = val_iterator<TBitCount, TDataType, const TValueType>;
val_container(TDataType* data = nullptr, size_t size = 0) : _data(data), _size(size)
{
static_assert(sizeof(TDataType) == 1, "sizeof TDataType must be 1 byte");
static_assert(TBitCount >= 1, "TBitCount must be at least 1 bit");
static volatile bool s = h::init();
if(size % h::bytes_count_in_block != 0)
throw std::invalid_argument(std::string("size: ") + std::to_string(size)+ " % " + std::to_string(h::bytes_count_in_block) + " != 0");
}
val_container(TDataType& data, size_t size) : val_container(&data, size) {}
iterator begin()
{ return iterator(_data); }
const_iterator begin() const
{ return const_iterator(_data); }
const_iterator cbegin() const
{ return const_iterator(_data); }
iterator end()
{ return iterator(_data + _size); }
const_iterator end() const
{ return const_iterator(_data + _size); }
const_iterator cend() const
{ return const_iterator(_data + _size); }
size_type size() const
{ return _size; }
bool empty() const
{ return begin() == end(); }
reference operator[](size_type n)
{ return *(iterator(_data) + n); }
const_reference operator[](size_type n) const
{ return *(const_iterator(_data) + n); }
};
It work for any TBitCount (I think).
What can be improved in this code?
Firstly, to implement a random access iterator in general, you need to implement the operations that are required to fulfill the RandomAccessIterator concept.
You will need to implement addition and subtraction with integers and compound assignment for each, subtraction of two iterators, subscript operator, less/greather than operator, both strict and non-strict, (in-)equality operator, pre- and post-increment and -decrement, dereference and the arrow operator.
See the documentation of iterator concepts for exact required behaviour for each of those operations.
Secondly, you must consider the fact that the elements returned by the iterator are less than byte sized. Clearly, since a byte is the smallest addressable object, you cannot have a reference to such smaller object (or rather, such fragments of objects).
What you can do is use a custom proxy class as your val_iterator::reference. The behaviour of the proxy should be to modify the referenced bits when assigned to, and be implicitly convertible to the value of the referenced bit range. This is the same way the std::vector<bool>::reference is implemented.
#ifndef HASHMAP_H
#define HASHMAP_H
#include <iostream>
#include <string>
#include <vector>
using namespace std;
enum Status{open , active, deactivated };
//template <typename T>
template</*typename Key,*/ typename T>
class hashmap{
private:
class Node{
public:
const string Key;
//vector<T> values;
T value;
Status status;
Node(string key, T val) :Key(key), value(val), status(active){}
void operator =(const Node &n){
string *ptr;
ptr = (string*)(&(this->Key));
*ptr = n.Key;
//Node(n);
this->status = n.status;
this->value = n.value;
}
Node() :status(open){}
Node(const string& key) :Key(key), status(active){}
//Node(const Node &n) : value(n.val), status(n.status){}
};
//typedef map<
unsigned int hash(const string& s, int tableSize){
unsigned int h = 0;
/*each(s)*/
for(auto it : s) h = 31 * h + unsigned(it);
return h % tableSize;
}
unsigned int hash(const string& s){
return hash(s, table_size);
}
int table_size = 103;
vector<Node> table;
typedef typename vector<Node>::iterator iter;
public:
//default constructor
hashmap(){
table = vector<Node>(table_size);
}
//copy constructor
hashmap(const hashmap& x){
table = x.table;
//for (auto it = )
}
//assignment operator //has been removed
hashmap& operator=(const hashmap& x){
this->table.erase(this->table.begin(), this->table.begin() + 103);
for ( int i = 0; i < x.table_size; i++){
this->table.push_back(x.table.at(i));
}
return *this;
}
//destructor
~hashmap(){
table.clear();
}
//index operator
T& operator[](const string x){
int h = hash(x, table.size());
if (table[h].Key == x){
return (table[h].value);
}
else {
Node* n = new Node(x);
table[h] = *n;
return (table[h].value);
}
}
//Node test
void okay(const string x,int i){
Node *temp = new Node(x, i);
cout << temp->status << endl;
/*cout << table[1].status << endl;
cout << table[2].status << endl;
table.at(0) = (*temp);
cout << table[0].Key << endl;
cout << table[0].value << endl;
cout << table[3].status << endl;*/
}
int stride(int x){
return (7-x%7);
}
//find()
iter find(const string& x){
int h = hash(x);
int s = stride(h);
int t = table_size;
int z;
//for (int i = 0; i < t; i++){
for (int i = hash(x, table_size) % t; i != t; i = (i + stride(h)) % t){
z = (h + i*s) % table_size;
if (table[z].status == open) return NULL;
if (table[z].status == deactivated) continue;
if (table[z].Key == x) return &table[h];
}
return table.end();
}
//begin()
iter begin(){
return table.begin();
}
//end()
iter end(){
return table.end();
}
};
#endif // !HASHMAP_H
Everything seems to be working fine except the find function. It's suppose to probe through the vector and return values upon conditions but the problem I'm having is I get these errors about return type conflicts.
Error2error C2664: 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap::Node>>>::_Vector_iterator(const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap::Node>>> &)' : cannot convert argument 1 from 'hashmap<int>::Node *' to 'const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &'
Error1error C2664: 'std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>>::_Vector_iterator(const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &)' : cannot convert argument 1 from 'int' to 'const
std::_Vector_iterator<std::_Vector_val<std::_Simple_types<hashmap<int>::Node>>> &'
How can I edit the iterator to fix this?
thank you.