Using functor with definable state as unordered_set hash function - c++

I'm trying to use a functor with definable state as the hasher for an unordered_set, the problem i'm faced with is I doesn't know how to initialize the functor passed as the template parameter. It would be something like this.
class A{
private:
class Hasher{
private:
int a;
public:
Hasher(int val=3):a(val){};
size_t operator()(const string & s) const{
return s[0]*a;
}
};
unordered_set<string,Hasher??> us;
int hasher_val;
public:
A(int h_val):hasher_val(h_val){};
}
The problem is, how can I define "a" for a value different to 3?

std::unordered_set's constructor has optional parameters which can be used to initialize its hash instance:
unordered_set<string,Hasher> us;
int hasher_val;
public:
A(int h_val) : us{51, Hasher(4)}, hasher_val{h_val}{};
One slightly uncomfortable fact is that the hash instance is the second parameter, and you have to explicitly specify your hash bucket size, instead of relying on the wisdom of your C++ library to provide a suitable default (in my example, I just picked 51 off the top of my head, which is probably very, very wrong but that would be a different question to mull over...).
You should spend a few minutes digging into your header files to determine what default your C++ implementation uses, for the set's bucket size, and supply the same value.
P.S. The same approach is used with all library containers: their constructors' parameters are all defaulted, making it possible to explicitly construct them using a custom hash class instance, a custom comparator class instance, etc...

Related

How to increase static int value in a template class within constructor and destructor functions?

Let's assume we have a template class ptr. The constructor function of ptr class can take values of int, double, another handmade structure etc since it is a template class.
I want to see exactly how many times these constructors and destructors are called and also the type of the data that it has been called for. Is this possible to see?
Right now I have a static int value in the template class and 2 constructors (1 default constructor) and 1 destructors in which I increase/decrease the value of the static int value.
template<class T>
class ptr
{
private:
T* data;
public:
ptr();
ptr(T* data);
~ptr();
static int number;
};
template<class T>
int ptr<T>::number = 0;
How can I see for which types these constructors and destructor are called? All I see now the value of the static int, not for which type it is called.
If you do wish to count all instances (independent of type) you might try to give them a common non-templated super class:
class uniptr {
protected:
static int number;
}
template<class T>
class ptr: public uniptr
{
private:
T* data;
public:
ptr();
ptr(T* data);
~ptr();
};
This seems to do what you want with some reasonable encapsulation. If it's not immediately clear this works because there is only one class uniptr declared (and therefore only one static int) even though there might be multiple versions of ptr used (likeptr<int> and ptr<String>).
I want to see exactly how many times these constructors and destructors are called...
Well that's easy, you store that number in ptr<T>::number, so yes, it's possible to see. For example, to see how many times ptr<Foo> has been instantiated, use ptr<Foo>::number.
and also the type of the data that it has been called for
It's not possible to get that kind of information from your template. That's essentially asking: what are all instances ptr whose constructor has been called?
What you could do, is define a global map of std::type_index to int. Since that map wouldn't be limited to one template, it could keep track of calls to costructors of any instance of ptr.
It might be worth noting that you can only get an implementation defined, mangled, name of the type using std::type_index, so if you want a prettier typename, then you'll need some way to map the std::type_index to what you want. If you limit the possible types to select few, you could keep your own map of std::type_index to std::string and use that for printing, or you could use platform specific demangling.
EDIT:
Storing the type - count map in a non-template parent class (in the similar way as Elemental's answer for total count) would probably be more appropriate than storing it globally.

How to create user defined type template class object C++

I am struggling with allowing user to select data type template will be created as.
Since template type must be defined on compile, I must specify data type template will use eg(string,int, so on), but that means I cannot change it latter on, from lets say string to int even if my template supports it, because template class object was declared as string.
My class declaration below:
template <class T>
class MyHashTable
{
public:
string deleted="deleted";
unsigned short tableSize;
// array of vectors, hash table container
vector<T>* myTable;
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize])
{
this->tableSize=tableSize;
}
object declaration outside class
MyHashTable <string>* myChainedTable=NULL ;
string tableType;
object initialization
if (myChainedTable)
{
delete myChainedTable;
myChainedTable=NULL;
}
getType();
if (!myChainedTable)
{
if (tableType=="string")
myChainedTable= new MyHashTable<string>(length);
if (tableType=="char")
MyHashTable<char> myChainedTable(length); // no difference with or without using new keyword
if (tableType=="double")
MyHashTable<double> myChainedTable(length);
if (tableType=="float")
MyHashTable<float> myChainedTable(length);
if (tableType=="int")
MyHashTable<int> myChainedTable(length);
cout<<tableType<<" table of size "<< length<<" created"<<endl;
I attempted passing class object to functions instead of having it as global variable, but couldnt get it work either.
What I really need is single template object that can have: int,string,char,double,float types, I have 3 functions that need to have access to template class object, and having 5 different objects and 200 lines of if statements for each situation sounds like worst possible solution.
I been stuck on this for a while and just cant figure out how to do it and any help will be appreciated.
void getType()
{
cout<<"Enter table type, types available: int, char, float, double, string.\n";
tableType=getInput();
while((tableType != "int")&&(tableType !="float")&&(tableType !="double")&&(tableType!="char")&&(tableType !="string"))
{
cout<<"Invalid type, please try again "<<endl;;
tableType=getInput();
}
}
Your question is at the boarder between templates and variants.
The template is compile time. So you have to choose at compile time the type you want for your object. Your conditional approach can't work (see comments to question).
On the other side, you seem to need a dynamic choice of type at runtime.
If you want to go on on template way: (edit based on comments)
You'd need to have all the templates inherit from a single polymorphic base class (one common interface with virtual functions). Example:
class MyHashBase // common base class for all templates
{
public:
virtual void addElement(void *ptrelem) = 0; // adding an element must be implemented by template. With void* since future template type unknown from base class
virtual void displayAll() = 0;
};
The templates would need then implement the virtual functions:
template <class T>
class MyHashTable : public MyHashBase
{
public:
unsigned short tableSize;
vector<T>* myTable; // I leave it as it is, but you could implement these as vector<T> instead of vector<T>*
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize]), tableSize(tableSize)
{ }
void addElement(void* ptrelem)
{ myTable->push_back(*reinterpret_cast<T*>(ptrelem)); } // reinterpret the void* of the common interface as a T*
void displayAll()
{ copy(myTable->begin(), myTable->end(), ostream_iterator<T>(cout, "\n")); }
};
You could then have your myChainedTable be a pointer to the common base type, and intialise this pointer in the way you did with the string case (i.e. using new).
MyHashBase *myChainedTable = nullptr;
//...
if (tableType == "string")
myChainedTable = new MyHashTable<string>(length);
else if (tableType == "double")
myChainedTable = new MyHashTable<double>(length);
//...
You could then use the common API, for example if tableType is "double":
double d1 = 3.1415, d2 = 1.4142;
myChainedTable->addElement(&d1); // ATTENTION: you must ensure to provide pointer to the correct data type
myChainedTable->addElement(&d2);
myChainedTable->displayAll();
You'll certainly have a coupe of if required in the calling code, but you could reduce them to minimum by carefully designing the base class (for example, you could add a virtual clone function, to duplicate the data without need to know the type by the caller).
However, using a single signature for the common functions of the base class is cumbersome. To make the virtualisation possible you need to pass parameters through void* pointer which is not so nice and rather error prone.
Alternate way with variants
You could also use boost variants which are meant for managing objects with dynamic definition of types.
In this case you would not need template for your own data structure. You would create a MyHashTable with elements of type boost::variant< int, std::string, ... >.
You could then access to the right value of the object if you know its type (as in your myChainedTable) by using: boost::get<int> (element) (or boost::get<string>(), ...).
If you don't know the type on an element you could use the concept of "visitor" to chose automatically the appropriate function to exectue depending on the type.
Edit: alternate way with unions:
If you're not allowed to use variants another alternative could be use a union. I don't know the topic of you rassignment, but you have the choice whether you use a union to define the elements (like the variants, without templates) or to use a template type as you did, but define myChainedTable to be a union of pointers to the different template instantiations. But yes, it requires a lot of ifs...
Templates are resolved at compile time. Your container type is resolved at runtime. Templates are clearly not the solution here. The first thing that comes to my mind is a combination of boost::any and std::vector instead.

OOP - How should this be done?

I have a class that has the following variables/members:
First Name
Last Name
Age
Address
etc..
I want to create getter-methods for each of them that returns the values. This could become quite large depending on the class.
Is there a quicker or more object-oriented way that would allow me to do this just using one method? The only way I can think about is to have a method that takes a parameter of the name of the variable to be returned; however, the types for the method would change depending on if it was returning a string, int etc..
Does anyone have a solution?
Why do you need those values outside the class? If you have code that is not in Person that calls 4 or 5 Person GetWhatever() methods and glues the strings together, stuffs commas between them and so on, move that code into Person. Do that enough and no code outside Person needs to call your getters.
Some classes are logic-free, they just hold values, and they expect outside objects to do all the work. In C++, using a struct for that makes your intention clear. If you insist that code outside Person needs to arbitrarily access elements of Person, it's probably a struct, not a class. If you insist it's a class, prove it by adding some actual business logic to it.
No, there is no "better" way which is still object-oriented. You should define one public "getter" method for each private member variable which needs to be access outside the class. You should also define a setter method, if the variable is meant to be set from outside the class.
If you want easy to define setter/getter - make it on single member level. Make member template with setter/getter and define is as public element of your class:
template <class Type>
class Member {
public:
Member(const T& value = T()) : value(value) {}
void setValue(const Type& t) { value = t; }
T getValue() const { return value; }
private:
T value;
};
Use it in your class:
class Person {
public:
Member<std::string> firstName;
Member<std::string> lastName;
Member<std::string> address;
Member<unsigned> age;
};
And usage:
int main() {
Person one;
one.firstName.setValue("Joe");
one.age.setValue(33);
}
If your need some constraints (like range checking) then define some RangeCheckingMember template. If you need the members to be dependent on each others - then make relationship between them by pointers/references.
Consider making that parameter lookup using a template member function that takes a default value in a given type.
template<typename ValueType>
const ValueType& get(const KeyType& key, const ValueType& default value) {
...
};
You still have to enumerate (or otherwise list) a KeyType of all your values (or use std::string which might be fine in larger cases) and work back and forth with your storage on the ValueType.
So, this doesn't really help you much until you decide you need arbitrarily large or completely dynamic values. At this point, you need to implement a map which can hold any type which requires either hideous unions or a template wrapper derived class from a common base class used in the map.
The upside to this is that a getKeys() method can present all of the keys available in the class -- something quite useful for dynamic GUIs and message handling.
If you are using a library in which everything subclasses some Object class (QObject for example), you can use a map of (string, object) to hold all your data and then access it with:
Object get(string name) { return memebers[name]; }
members is std::map<std::string, Object>
You will need to use type casts of course.
Button* my_var = static_cast<Button*>(my_class.get("my_button"));
// get returns Object
You can also use Qt's property system if you use Qt. This is not standard c++, but qmake and moc work on many operating systems.
all right.since you know what you want.
void get(int flag, void *return_value)
get the return_value typd casting to what you want.
thanks

How to share different objects between some classes

what is the best way to share different objects between some classes in a generic manner?
For example class A can store an object o with a string as a key in a register and class B can access it using the key.
My first idea was to create a register (singleton) which has a hashtable as a member using a string as the key and a void pointer as the value. But there must be a better solution for this?
From your clarification:
template <typename OB>
class A {
std::unordered_map<std::string, OB> hash;
public:
OB const& get(std::string const&) const;
void add(OB const& object, std::string const&);
};
That is to say, A<int> is a class that stores int objects by name, and A<std::set<float>> is a class that stores sets of floats by name. You can't mix them. That's in line with the basic C++ philosophy: the type of theA.get("foo") is determined at compile time, not by what you put in at runtime.
In C++, you can however "mix" multiple derived types, if you'd need this for your particular case. That's a bit more complicated:
template <typename Base>
class A {
std::unordered_map<std::string, std::unique_ptr<Base>> hash;
public:
Base const& get(std::string const&) const;
template<typename Derived> void add(std::string const& name, Derived const& object)
{
std::unique_ptr<Base> copy(new Derived(object));
hash.emplace(std::make_pair(name, std::move(copy)));
}
};
There's some slight trickery here as hash should be the only owner of the copy, but it's constructed outside and therefore needs to be moved it. (For extra-fancy, I could add a Derived&& overload that eliminates that copy too)
I would suggest that all the classes that you must register have a common supertype.
For instance, if you have to store instances of classes One, Two, and Three you could define a (possibly empty) class Object from which your class can derive:
class Object {}
class One : public Object { /* One's member and methods */ }
class Two : public Object { /* Two's member and methods */ }
class Three : public Object { /* Three's member and methods */ }
If you follow MSalters question you can then declare a A<Object*>.
If you cannot have one supertype (for instance because you cannot change One, Two or Three) you may look at Boost.Variant. Again, you can declare a A<boost::variant<One, Two, Three> >.
The first question is: how does B know the type of the stored object,
and what it can do with it? Perhaps the simplest solution is just to
have one registry per type. Alternatively, something like
boost::variant can be used, or you can ensure that all types derive
from a common base, and store a pointer to that. Unless you actually
need to support polymorphism (e.g. operating on an object without
knowing its exact type), I'd avoid the pointer solution, however.
The best way is to use a shared_ptr, instead of a naked pointer. If you have a C++11 compliant compiler, shared_ptr is in the std namespace. Otherwise, use the Boost implementation.

Extension of STL container through composition or free functions?

Say I need a new type in my application, that consists of a std::vector<int> extended by a single function. The straightforward way would be composition (due to limitations in inheritance of STL containers):
class A {
public:
A(std::vector<int> & vec) : vec_(vec) {}
int hash();
private:
std::vector<int> vec_
}
This requires the user to first construct a vector<int> and a copy in the constructor, which is bad when we are going to handle a sizeable number of large vectors. One could, of course, write a pass-through to push_back(), but this introduces mutable state, which I would like to avoid.
So it seems to me, that we can either avoid copies or keep A immutable, is this correct?
If so, the simplest (and efficiency-wise equivalent) way would be to use a typedef and free functions at namespace scope:
namespace N {
typedef std::vector<int> A;
int a_hash(const A & a);
}
This just feels wrong somehow, since extensions in the future will "pollute" the namespace. Also, calling a_hash(...) on any vector<int> is possible, which might lead to unexpected results (assuming that we impose constraints on A the user has to follow or that would otherwise be enforced in the first example)
My two questions are:
how can one not sacrifice both immutability and efficiency when using the above class code?
when does it make sense to use free functions as opposed to encapsulation in classes/structs?
Thank you!
Hashing is an algorithm not a type, and probably shouldn't be restricted to data in any particular container type either. If you want to provide hashing, it probably makes the most sense to create a functor that computes a hash one element (int, as you've written things above) at a time, then use std::accumulate or std::for_each to apply that to a collection:
namespace whatever {
struct hasher {
int current_hash;
public:
hasher() : current_hash(0x1234) {}
// incredibly simplistic hash: just XOR the values together.
operator()(int new_val) { current_hash ^= new_val; }
operator int() { return current_hash; }
};
}
int hash = std::for_each(coll.begin(), coll.end(), whatever::hasher());
Note that this allows coll to be a vector, or a deque or you can use a pair of istream_iterators to hash data in a file...
Ad immutable: You could use the range constructor of vector and create an input iterator to provide the content for the vector. The range constructor is just:
template <typename I>
A::A(I const &begin, I const &end) : vec_(begin, end) {}
The generator is a bit more tricky. If you now have a loop that constructs a vector using push_back, it takes quite a bit of rewriting to convert to object that returns one item at a time from a method. Than you need to wrap a reference to it in a valid input iterator.
Ad free functions: Due to overloading, polluting the namespace is usually not a problem, because the symbol will only be considered for a call with the specific argument type.
Also free functions use the argument-dependent lookup. That means the function should be placed in the namespace the class is in. Like:
#include <vector>
namespace std {
int hash(vector<int> const &vec) { /*...*/ }
}
//...
std::vector<int> v;
//...
hash(v);
Now you can still call hash unqualified, but don't see it for any other purpose unless you do using namespace std (I personally almost never do that and either just use the std:: prefix or do using std::vector to get just the symbol I want). Unfortunately I am not sure how the namespace-dependent lookup works with typedef in another namespace.
In many template algorithms, free functions—and with fairly generic names—are often used instead of methods, because they can be added to existing classes, can be defined for primitive types or both.
One simple solution is to declare the private member variable as reference & initialize in constructor. This approach introduces some limitation, but it's a good alternative in most cases.
class A {
public:
A(std::vector<int> & vec) : vec_(vec) {}
int hash();
private:
std::vector<int> &vec_; // 'vec_' now a reference, so will be same scoped as 'vec'
};