I have a class that contains a tree structure implemented by a vector< vector< Node > > where Node contains a bunch of attributes exposed via getters/setters.
class Tree
{
vector< vector< Node > > mGrid;
printTree(std::ostream& output = std::cout);
};
class Node
{
double property1 { return mProp1; }
double property2 { return mProp2; }
};
printTree() is currently hardwired to use property tstep:
void Tree::printTree( ostream& output )
{
...
for (unsigned t = 0; t < mGrid.size(); ++t)
{
toPrint = "";
for (unsigned state = 0; state < mGrid[t].size(); ++state)
{
toPrint += to_string_with_precision( mGrid[t][state].tstep(), 1 );
...
Is there some slick / convenient / object-oriented way of generalizing this function so that it can print out any of Node's properties (rather than only spitting out the hardwired tstep() property or essentially doing the same thing via if/then statements).
I've done things like this in C using function pointers, but this is C++ and the C++ FAQ says not to mess with pointers to member functions.
You might want template function:
class Tree
{
vector< vector< Node > > mGrid;
public:
template <typename F>
void ForEachNode(F&& f) {
int i = 0;
for (auto& v : mGrid) {
int j = 0;
for (auto& node : v) {
f(node, i, j);
++j;
}
++i;
}
}
};
Then you may do
void printTreeProp1(Tree& tree) {
tree.ForEachNode([](const Node& node, int i, int j) {
if (i != 0 && j == 0) {
std::cout << std::endl;
}
std::cout << node.property1() << " ";
});
}
1st op all you loops are ignoring the first element. vector is zero based and you are using ++t and ++state which increases the values on top of the loop. That means you are never accessing the 0th element (mGrid[0] and mGrid[t][0]).2nd, you did noy include the definition of tstep(), so we don't know what you are getting back. Assuming you want to print each dimension of your 2 dimension array, I think you have to break it to peaces. Something like this:
class Node
{
protected:
double mProp1;
double mProp2;
public:
double GetProp1(void) {return mProp1;}
double GetProp2(void) {return mProp2;}
String tStep(void) {return L"";} // add your code here
};
class NodeRow : public std::vector<Node>
{
public:
void Print(std::ostream& output)
{
iterator i;
String tStr;
for(i = begin(); i != end(); i++)
tStr += /*to_string_with_precision(*/i->tStep()/*, 1)*/;
output << tStr.c_str() << L"\r\n";
}
};
class Node2D : public std::vector<NodeRow>
{
public:
void Print(std::ostream& output = std::cout)
{
iterator i;
for(i = begin(); i != end(); i++)
i->Print(output);
}
};
Related
I'm learning to build a hashtable with c++. And find this post: https://www.geeksforgeeks.org/c-program-hashing-chaining/.
It implemented a simple and basic version of hashtable (not production level) with chaining to fix hash collision issue.
I followed the post and run it locally and it works as expected. The implementation is as following:
#include <iostream>
#include <list>
using namespace std;
class Hash {
int BUCKET;
list<int> *table; // confusing point1
public:
Hash(int V);
void insertItem(int key);
void deleteItem(int key);
int hashFunction(int x) {
return (x % BUCKET);
}
void displayHash();
};
Hash::Hash(int b) {
this->BUCKET = b;
table = new list<int>[BUCKET]; // confusing point2
}
void Hash::insertItem(int key) {
int index = hashFunction(key);
table[index].push_back(key);
}
void Hash::deleteItem(int key) {
int index = hashFunction(key);
list <int> :: iterator i;
for (i = table[index].begin(); i != table[index].end(); i++) {
if (*i == key) {
break;
}
}
if (i != table[index].end()) {
table[index].erase(i);
}
}
void Hash:: displayHash() {
for (int i = 0; i < BUCKET; i++) {
cout << i;
for (auto x : table[i]) {
cout << "-->" << x;
}
cout << endl;
}
}
// Driver program
int main()
{
// array that contains keys to be mapped
int a[] = {15, 11, 27, 8, 12};
int n = sizeof(a)/sizeof(a[0]);
// insert the keys into the hash table
Hash h(7); // 7 is count of buckets in
// hash table
for (int i = 0; i < n; i++)
h.insertItem(a[i]);
// delete 12 from hash table
h.deleteItem(12);
// display the Hash table
h.displayHash();
return 0;
}
I have two confusing points about this implementation:
list<int> *table : table should be buckets array. Right? list<int>
* should be list type pointer, right? How it works here?
table = new list<int>[BUCKET]: I checked many list related
documents. but didn't find how the [] works?
list<int> *table : table should be buckets array. Right? list<int>* should be list type pointer, right? How it works here?
In this awful code, table is a pointer to a list<int>, but when you have a pointer to an item and happen to know there's an array of contiguous elements there, you can index it like an array, so table[0] is the same as *table, table[1] would be the next list<int> in memory after table[0] and so on.
table = new list<int>[BUCKET]: I checked many list related documents. but didn't find how the [] works?
This is the initialisation that creates an array of list<int> objects and saves their address in table, so we do indeed "happen to know" that the array is there and can index table as an array. For example, inside the displayHash function you see for (auto x : table[i]) - that means x takes on each value from the list<int> at bucket i which is table[i].
The code also needs a destructor to delete[] table, or all the memory will be leaked when the Hash object's default destructor runs without doing any clean-up.
You should also be aware that it lets you insert multiple copies of the same key - a proper and full implementation of this functionality is be std::unordered_multiset.
Cleaning it up minimally - without taking the next steps to use templates to let you use it for other types, add iterators etc.:
class Hash {
vector<list<int>> table_;
public:
Hash(size_t size) : table_{size} { }
void insert(int key) {
table_[bucket(key)].push_back(key);
}
void erase(int key) {
auto& bucket_list = table_[bucket(key)];
auto it = find(bucket_list.begin(), bucket_list.end(), key);
if (it != bucket_list.end())
bucket_list.erase(it);
}
int bucket(int key) const {
return hash(key) % table_.size();
}
static int hash(int key) {
return key;
}
// example usage: my_hash.display(std::cout);
void display(std::ostream& os) const {
for (size_t i = 0; i < table_.size_; ++i) {
os << '[' << i << ']';
for (auto x : table[i])
os << "-->" << x;
os << '\n';
}
}
// extensions ===================================
bool contains(int key) const {
auto& bucket_list = table_[bucket(key)];
auto it = find(bucket_list.begin(), bucket_list.end(), key);
return it != bucket_list.end();
}
// example usage:
// my_hash.visit([](auto key) { std::cout << key << '\n'; });
template <typename Functor)
void visit(Functor functor) const {
for (size_t i = 0; i < table_.size_; ++i)
for (auto x : table[i])
functor(x);
}
};
basically, I want to implement document type converter. I've designed pretty straight-forward solution:
DocTypeParser : Parser will converts file into tree structure of nodes, representing different elements (headers, lists, bold texts, ...)
DocTypePrinter : Printer will deconstruct that tree back into text file
So far so good, but I came across nasty problem - The connection between tree nodes is estabilished through std::vector<Node *> and I am not sure how to determine what child class is being processed.
My demo code:
class Node
{
public:
Node()
{
}
~Node()
{
for (auto it : Leaf)
delete it;
}
Node &Add(Node *leaf)
{
Leaf.push_back(leaf);
return *this;
}
std::vector<Node *> Leaf;
};
class NodeA : public Node
{
public:
NodeA() : Node()
{
}
};
class Printer
{
public:
Printer() = default;
std::string Print(Node &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<n>";
for (; i < k; ++i)
res += Print(*(n.Leaf[i]));
res += "</n>";
return res;
}
std::string Print(NodeA &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<A>";
for (; i < k; ++i)
res += Print(*(n.Leaf[i]));
res += "</A>";
return res;
}
};
int main(int argc, const char *argv[])
{
NodeA tree;
tree.Add(new NodeA).Add(new NodeA);
Printer p;
std::cout << p.Print(tree) << std::endl;
return 0;
}
Desired result: <A><A></A><A></A></A>
Actual result: <A><n></n><n></n></A>
I pretty much understand what is the problem (vector stores Node pointers, not NodeChild pointers), but not that sure how to overcome that. dynamic_cast seems to be not-the-solution-at-all.
So finally question - is there cure for me or am I longing for the wrong design altogether?
You used type erasure wrongly. Your nodes accessed by Node* , so *(n.Leaf[i]) expression returns type Node, not NodeA.
What you do resembles visitor pattern, to recognize which class is which you have to use a virtual method in Node class and override it in NodeA, calling it with dispatcher as argument (classic visitor) or calling it from dispatcher you can recognize which instance is which.
In first case node would call the Print method and pass it *this.
This is minimal rework of your code, but I think, it needs honing\optimizing. Depends on what your actual task is, vistor might be a little too excessive.
#include <string>
#include <iostream>
#include <vector>
class Node;
class NodeA;
class AbstractPrinter
{
public:
virtual std::string Print(Node &n) =0;
virtual std::string Print(NodeA &n) =0;
};
class Node
{
public:
Node()
{
}
virtual ~Node()
{
for (auto it : Leaf)
delete it;
}
Node &Add(Node *leaf)
{
Leaf.push_back(leaf);
return *this;
}
virtual std::string Print(AbstractPrinter& p)
{
return p.Print(*this);
}
std::vector<Node *> Leaf;
};
class NodeA : public Node
{
public:
NodeA() : Node()
{
}
// if not override this, it would use Node
virtual std::string Print(AbstractPrinter& p) override
{
return p.Print(*this);
}
};
class Printer : public AbstractPrinter
{
public:
Printer() = default;
std::string Print(Node &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<n>";
for (; i < k; ++i)
res += n.Leaf[i]->Print(*this);
res += "</n>";
return res;
}
std::string Print(NodeA &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<A>";
for (; i < k; ++i)
res += n.Leaf[i]->Print(*this);
res += "</A>";
return res;
}
};
int main(int argc, const char *argv[])
{
NodeA tree;
tree.Add(new NodeA).Add(new NodeA);
Printer p;
std::cout << tree.Print(p) << std::endl;
return 0;
}
Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.
I find myself writing a lot of functions that begin with many preconditions, and then I have to figure out how to handle all the invalid inputs and write tests for them.
Note that the codebase I work in does not allow throwing exceptions, in case that becomes relevant in this question.
I am wondering if there is any C++ design pattern where instead of having preconditions, input arguments are passed via wrapper classes that guarantee invariants. For example suppose I want a function to return the max value in a vector of ints. Normally I would do something like this:
// Return value indicates failure.
int MaxValue(const std::vector<int>& vec, int* max_value) {
if (vec.empty()) {
return EXIT_FAILURE;
}
*max_value = vec[0];
for (int element : vec) {
if (element > *max_value) {
*max_value = element;
}
}
return EXIT_SUCCESS;
}
But I am wondering if there is a design pattern to do something like this:
template <class T>
class NonEmptyVectorWrapper {
public:
static std::unique_ptr<NonEmptyVectorWrapper>
Create(const std::vector<T>& non_empty_vector) {
if (non_empty_vector.empty()) {
return std::unique_ptr<NonEmptyVectorWrapper>(nullptr);
}
return std::unique_ptr<NonEmptyVectorWrapper>(
new NonEmptyVectorWrapper(non_empty_vector));
}
const std::vector<T>& vector() const {
return non_empty_vector_;
}
private:
// Could implement move constructor/factory for efficiency.
NonEmptyVectorWrapper(const std::vector<T>& non_empty_vector)
: non_empty_vector_(non_empty_vector) {}
const std::vector<T> non_empty_vector_;
};
int MaxValue(const NonEmptyVectorWrapper<int>& vec_wrapper) {
const std::vector<int>& non_empty_vec = vec_wrapper.vector();
int max_value = non_empty_vec[0];
for (int element : non_empty_vec) {
if (element > max_value) {
max_value = element;
}
}
return max_value;
}
The main pro here is that you avoid unnecessary error handling in the function. A more complicated example where this could be useful:
// Finds the value in maybe_empty_vec which is closest to integer n.
// Return value indicates failure.
int GetValueClosestToInt(
const std::vector<int>& maybe_empty_vec,
int n,
int* closest_val);
std::vector<int> vector = GetRandomNonEmptyVector();
for (int i = 0; i < 10000; i++) {
int closest_val;
int success = GetValueClosestToInt(vector, i, &closest_val);
if (success) {
std::cout << closest_val;
} else {
// This never happens but we should handle it.
}
}
which wastefully checks that the vector is non-empty each time and checks for failure, versus
// Returns the value in the wrapped vector closest to n.
int GetValueClosestToInt(
const NonEmptyVectorWrapper& non_empty_vector_wrapper,
int n);
std::unique_ptr<NonEmptyVectorWrapper> non_empty_vector_wrapper =
NonEmptyVectorWrapper::Create(GetRandomNonEmptyVector());
for (int i = 0; i < 10000; i++) {
std::cout << GetValueClosestToInt(*non_empty_vector_wrapper, i);
}
which can't fail and gets rid of the needless input checking.
Is this design pattern a good idea, is there a better way to do it, and is there a name for it?
I'm having trouble outputting my vector of lists:
class index_table {
public:
index_table() { table.resize(128);}
void insert(string &, int );
private:
class entry
{
public:
string word;
vector <int> line;
};
vector< list <entry> > table;
};
I've got it so that it will fill up:
int main ()
{
index_table table;
string word,
int num = 5; //this is going to a random number. 5 is a temp. place holder.
while (cin >> word)
table.insert(word, num);
}
but how to output it? I've tried many different approaches, but a lot of them are giving me errors.
Do I have to overload the operator? I'm not entirely sure how I will be able to do it.
Assuming you really have a good reason to use std::vector< std::list<entry> >, then based on the given structure, printing of words might look like this:
class index_table {
public:
void print() {
for (size_t i = 0; i < table.size(); ++i) {
std::list<entry>::iterator li;
for (li = table[i].begin(); li != table[i].end(); ++li)
std::cout << li->word << " ";
}
}
...
private:
std::vector< std::list<entry> > table;
...
};
If your compiler supports C++11, you can use two range based nested for loops. Look in the function void index_table::dump().
// Output function
void index_table::dump() {
for (list<entry> &le : table) {
for (entry &e : le) {
e.dump();
}
}
}
I also created a function dump() in the entry class, which outputs the contents of two variables, which is now made private.
class index_table {
public:
index_table() {
table.resize(128);
}
void insert (int,string&,int);
void dump();
private:
class entry {
private:
string word;
int value;
public:
entry (string word, int value) {
this->word = word;
this->value = value;
}
void dump() {
cout << "Word/value is: " << word << "/" << value << endl;
}
};
vector< list <entry> > table;
};
void index_table::insert(int c, string &key, int value) {
//void index_table::insert(string &key, int value) {
entry obj(key, value);
table[c].push_back(obj);
}
// Output function
void index_table::dump() {
for (list<entry> &le : table) {
for (entry &e : le) {
e.dump();
}
}
}
int main (int argc, char **argv) {
index_table mytable;
string a = "String 0-A";
string b = "String 0-B";
string c = "String 1-A";
string d = "String 1-B";
string e = "String 6-A";
string f = "String 6-B";
mytable.insert(0, a, 1);
mytable.insert(0, b, 2);
mytable.insert(1, c, 3);
mytable.insert(1, d, 4);
mytable.insert(6, e, 3);
mytable.insert(6, f, 4);
mytable.dump();
}
Program outputs:
Word/value is: String 0-A/1
Word/value is: String 0-B/2
Word/value is: String 1-A/3
Word/value is: String 1-B/4
Word/value is: String 6-A/3
Word/value is: String 6-B/4
PS: I also changed your code a bit to make it run more easily for my test.
//This is the simple solution for outputting vector of lists.
#include <bits/stdc++.h>
using namespace std;
main()
{
vector<list<int>> my_vector; //creating vector of lists;
list<int> my_list;
for(int i = 0; i < 5; i++)
my_list.push_back(i);
my_vector.push_back(my_list); // pushing a list y to a vector
for (vector<list<int>>::iterator it = my_vector.begin(); it != my_vector.end(); ++it)
for (list<int>::iterator it2 = it->begin(); it2 != it->end(); ++it2)
cout << *it2 << ", ";
}