How to using boost::unordered_set with custom class? - c++

I'm having a hard time calling hash_value.
From this post, I want to apply to vector<vector<E>> where E is a custom object.
My codes as follows:
struct E;
class myclass {
private:
vector<E> lhs;
public:
myclass(const vector<E>& v) :lhs{ v } { };
static size_t hash_value(const vector<E>& v) {
size_t seed = 0;
boost::hash_combine(seed, d.name);
boost::hash_combine(seed, d.scope);
return seed;
}
bool operator==(const vector<E> >& rhs) {
for (unsigned i = 0; i < lhs.size(); i++)
if (lhs[i].name != rhs[i].name || lhs[i].scope!= rhs[i].scope)
return false;
return true;
};
};
then i call this code:
void test(std::vector<std::vector<E>>& A)
{
boost::unordered_set < myclass > input_records(A.size());
for (BOOST_AUTO(it, A.begin()); it != (A.end());) {
auto k = input_records.insert(myclass{*it}); <<--
....
}
}
however i get an error:
Also, in some cases this code executes but hash_value is never called.
I'm not sure what am I missing?
How do I fix this?

You are trying to use boost::unordered_set<myclass>, which will internally use boost::hash<myclass>, which will look for a hash_value(myclass) function in the same namespace as myclass via Argument-Dependent Lookup. You made your hash_value() be a non-static member of myclass, so boost::hash will not be able to find it. But even if it could, it expects your hash_value() to take a single myclass object as a parameter, not a vector.
See Extending boost::hash for a custom data type in Boost's documentation.
Also, a class's operator== compares *this to another object. Inside of myclass, your operator== should take a single myclass object as a parameter, not a vector.
Try this instead:
struct E {
string name;
int scope;
};
size_t hash_value(const E& obj) {
std::size_t seed = 0;
boost::hash_combine(seed, obj.name);
boost::hash_combine(seed, obj.scope);
return seed;
}
class myclass {
private:
vector<E> vec;
public:
myclass(const vector<E>& v) : vec(v) {}
bool operator==(const myclass& rhs) const {
// vector has its own operator== for comparing elements in its array...
return vec == rhs.vec;
}
friend size_t hash_value(const myclass& obj) {
return boost::hash_range(obj.vec.begin(), obj.vec.end());
}
};
void test(std::vector<std::vector<E>>& A)
{
boost::unordered_set<myclass> input_records(A.size());
for (BOOST_AUTO(it, A.begin()); it != (A.end());) {
auto k = input_records.insert(*it);
...
}
}

Related

Use std::type_index as value in a map

I am trying to create a std::unordered_map where the value is a std::type_index. The following snippet works:
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
But this one doesn't run and throws an error:
std::unordered_map<int, std::type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
CS2512: 'std::type_index::type_index': no appropriate default constructor available.
I don't fully understand this error, what is the difference between the constructors in these examples? Is it possible to make a map where typeid(..) is the value instead of the key?
The issue is operator[], not the actual use of the map. The problem is if the key is not found, operator[] will assign a default value and return a modifiable reference to that value, which is impossible with std::type_index. You may use emplace, insert, try_emplace, or any other modifier that does not require a default constructor.
We could of course always create a nullable wrapper for type_info.
#include <typeindex>
#include <functional>
#include <unordered_map>
#include <cassert>
struct nullable_type_index
{
constexpr nullable_type_index() : ptr_(nullptr) {}
constexpr nullable_type_index(std::type_info const& ti) : ptr_(std::addressof(ti)) {}
constexpr operator bool() const
{
return bool(ptr_);
}
// I have avoided implicit conversion, but it could probably work
// without any surprises.
std::type_info const& get_type_info() const {
assert(ptr_);
return *ptr_;
}
constexpr bool operator==(nullable_type_index const& other) const {
return ptr_ && other.ptr_
? *ptr_ == *other.ptr_
: ptr_ == other.ptr_;
}
private:
std::type_info const* ptr_;
};
std::size_t hash_value(const nullable_type_index& nti)
{
return nti ? 0 : nti.get_type_info().hash_code();
}
bool operator==(nullable_type_index const& l, std::type_info const& r)
{
return l == nullable_type_index(r);
}
bool operator==(std::type_info const& l, nullable_type_index const& r)
{
return nullable_type_index(l) == r;
}
namespace std {
template<>
struct hash<nullable_type_index>
{
std::size_t operator()(nullable_type_index const& arg) const {
return hash_value(arg);
}
};
}
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, nullable_type_index> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}
or of course, now we have std::optional...
int main()
{
std::unordered_map<std::type_index, int> workingMap;
workingMap[typeid(int)] = 1;
workingMap[typeid(char)] = 2;
std::unordered_map<int, std::optional<std::type_index>> failingMap;
failingMap[1] = typeid(int);
failingMap[2] = typeid(char);
}

Using class member variable as reference

I would like to have a class member variable to be able to switch in between items in a map so that when it is modified, the content of the map is also modified.
Is there any way other than to use a pointer to the content of the map ? Old code only needed only variable, now the new one needs to switch. If I change the variable type, then all functions using this member variable need to be changed. Not complicated, but I would find it ugly to have * in front of it everywhere...
A reference variable cannot be rebound, so how can I achieve this ?
class A
{
std::map<std::string,std::vector<int>> mMyMap;
std::vector<int>& mCurrentVector;
std::vector<int>* mCurrentVectorPointer;
std::vector<int> mDefaultVector;
void setCurrentVector(int iKey);
void addToCurrentVector(int iValue);
}
A::A():
mDefaultVector(std::vector<int>())
mCurrentVector(mDefaultVector)
{
mMyMap["key1"] = std::vector<int>(1,1);
mMyMap["key2"] = std::vector<int>(1,2);
mCurrentVectorPointer = &mMyMap[0];
}
A::setCurrentVector(std::string iKey)
{
if(mMyMap.find(iKey) != mMyMap.end())
{
mCurrentVector = mMyMap[iKey]; //can't change a reference...
mCurrentVectorPointer = &mMyMap[iKey]; //could use pointer, but
}
}
A::addToCurrentVector(int iValue)
{
mCurrentVector.push_back(iValue);
//or
(*mCurrentVectorPointer).push_back(iValue);
//
mCurrentVectorPointer->push_back(iValue);
}
void main()
{
A wClassA();
wClassA.setCurrentVector("key2");
wClassA.addToCurrentVector(3);
wClassA.setCurrentVector("key1");
wClassA.addToCurrentVector(4);
}
mMyMap["key1"] now contains 1,4
mMyMap["key2"] now contains 2,3
You can't reseat a reference once it has been assigned which means you are left with using your other option, a pointer.
As I understand it, you're refactoring some existing code which only used a single vector, whereas now you need a map of vectors.
You're trying to achieve this with minimal modifications, and keeping the interface to the vector the same.
An option would be to use a local reference, assigned from your pointer.
class A
{
using Vector = std::vector<int>;
public:
A()
{
map_["key1"] = std::vector<int>(1,1);
map_["key2"] = std::vector<int>(1,2);
curr_vec_ = &map_["key1"];
}
void setCurrentVector(const std::string& key)
{
if(map_.find(key) != map_.end())
{
curr_vec_ = &map_[key];
}
}
void addToCurrentVector(int val)
{
assert(curr_vec_);
Vector& curr_vec = *curr_vec_; // local reference
curr_vec.push_back(val);
curr_vec[0] = 2;
// etc
}
private:
std::map<std::string, Vector> map_;
Vector* curr_vec_ = nullptr;
}
You may write some wrapper:
#define Return(X) noexcept(noexcept(X)) -> decltype(X) { return X; }
template <typename U>
class MyVectorRef
{
private:
std::vector<U>* vec = nullptr;
public:
explicit MyVectorRef(std::vector<U>& v) : vec(&v) {}
void reset(std::vector<U>& v) {vec = &v;}
// vector interface
auto at(std::size_t i) const Return(vec->at(i))
auto at(std::size_t i) Return(vec->at(i))
auto operator [](std::size_t i) const Return(vec->operator[](i))
auto operator [](std::size_t i) Return(vec->operator[](i))
template <typename ... Ts> auto assign(Ts&&... ts) Return(vec->assign(std::forward<Ts>(ts)...))
auto assign( std::initializer_list<U> ilist ) Return(vec->assign(ilist))
template <typename T> auto push_back(T&& t) const Return(vec->push_back(std::forward<T>(t)))
template <typename T> auto emplace_back(T&& t) const Return(vec->emplace_back(std::forward<T>(t)))
auto begin() const Return(vec->begin())
auto begin() Return(vec->begin())
auto end() const Return(vec->end())
auto end() Return(vec->end())
auto cbegin() const Return(vec->cbegin())
auto cend() const Return(vec->cend())
// ...
};
and then, use it:
class A
{
public:
A() : mCurrentVector(mDefaultVector) {
mMyMap["key1"] = std::vector<int>(1,1);
mMyMap["key2"] = std::vector<int>(1,2);
}
std::map<std::string, std::vector<int>> mMyMap;
std::vector<int> mDefaultVector;
MyVectorRef<int> mCurrentVector;
void setCurrentVector(std::string iKey)
{
auto it = mMyMap.find(iKey);
if (it != mMyMap.end())
{
mCurrentVector.reset(it->second);
}
}
void addToCurrentVector(int iValue)
{
mCurrentVector.push_back(iValue);
}
};
But I think it would be simpler to just create a getter in A and use directly a pointer:
class A
{
public:
A() : mCurrentVector(&mDefaultVector) {
mMyMap["key1"] = std::vector<int>(1,1);
mMyMap["key2"] = std::vector<int>(1,2);
}
std::map<std::string, std::vector<int>> mMyMap;
std::vector<int> mDefaultVector;
std::vector<int>* mCurrentVector;
std::vector<int>& GeCurrentVector() { return *mCurrentVector; }
void setCurrentVector(std::string iKey)
{
auto it = mMyMap.find(iKey);
if (it != mMyMap.end())
{
mCurrentVector = &it->second;
}
}
void addToCurrentVector(int iValue)
{
GeCurrentVector().push_back(iValue);
}
};

Inheritance vs class template specialization. Design dude

I have an implementation design trouble. I hope you can help me. Suppose I have the following class
class A
{
public:
vector<int> v() const { return m_v; }
bool isValid() const { return m_v.size() > m_components; }
int operator [] (const int index) const { return m_v[index]; }
...
private:
vector<int> m_v;
int m_components;
}
Now I want the m_v vector can be of different types, so I can template the class:
template<typename T>
class A
{
public:
vector<T> v() const { return m_v; }
T operator [] (const int index) const { return m_v[index]; }
...
private:
vector<T> m_v;
int m_components;
}
However, I realized that when the type T is for example double I need to extend class A and add more attributes, for example another vector<bool> m_foo; and change several methods that should use these new attributes.
Here is where I have the doubt. I think I have several options:
Option 1: I can make a non-templated base class A with the implementation of all the common methods, and derive several classes each one for each different type (with its own specific class attributes and method implementations), i.e.: Aint, Adouble, Afloat. This option requires that the vector<...> m_v; is stored at each derived class, and hence I have to replicate several times all the same code to access the m_v; attribute in each derived class. In the example, such methods are only v(), operator [] and isValid(), however in the real problem there are much more.
Option 2: Template specialization. I can specialize the class template for each type and hence provide only the implementation of the specific methods that change depending on the T type. However, this enforces to store a lot of stuff in the template class that is only used if T is of a specific type, i.e. the m_foo vector that is only used when T type is double (in the proposed example). Therefore, I am wasting memory. Moreover, it seems not very elegant or even coherent to implement a template class and provide template class specialization for almost most of the template types and store specific attributes that are only used for specific types.
I don't know if I managed to explain my problem well. Hope so.
Thank you in advance.
Javier.
This kind of depends.
General rule of thumb is asking yourself if "ADouble is-a A". When those have a is-a relationship you should use inheritance.
But you also have type dependency which is not really a "is-a" relationship.
You can also use both options: Having a base class with the common functionality which takes a template argument and having child classes with the additions they need. So you don't need to reimplement all the type dependend functions
So:
template<typename T>
class A
{
public:
vector<T> v() const { return m_v; }
T operator [] (const int index) const { return m_v[index]; }
...
private:
vector<T> m_v;
...
};
class ADouble : public A<double>
{
...
};
Btw: why do you think templates take more memory?
Partially specialise specific operations in your class (without specialising the whole class) with sub-operations.
#include <vector>
namespace detail
{
// general concept of indexing into something
template<class T> struct index_operation;
// indexing into most vectors
template <class T> struct index_operation<std::vector<T>>
{
T& operator()(std::vector<T>& v, std::size_t i) const
{
return v[i];
}
T const& operator()(std::vector<T> const& v, std::size_t i) const
{
return v[i];
}
};
// indexing into a vector<bool>
template <> struct index_operation<std::vector<bool>>
{
std::vector<bool>::reference operator()(std::vector<bool>& v, std::size_t i) const
{
return v[i];
}
std::vector<bool>::const_reference operator()(std::vector<bool> const& v, std::size_t i) const
{
return v[i];
}
};
}
template<typename T>
class A
{
using vector_type = std::vector<T>;
public:
std::vector<T> v() const { return m_v; }
decltype(auto) operator [] (const int index) const
{
auto op = detail::index_operation<vector_type>();
return op(m_v, index);
}
private:
std::vector<T> m_v;
};
I will try to formulate the question with an example closely to my real problem although it becomes a longer post.
Option1: Consider the following class implementation based on templates and template specialization.
template<typename T>
class A
{
public:
A() {}
vector<T> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
T operator [] (const int i) const { return m_v[i]; }
T& operator [] (const int i) { return m_v[i]; }
int components() const { return m_components; }
double value() const { return m_value; }
void method1();
private:
vector<T> m_v;
int m_components;
double m_value;
vector<bool> m_indices; // this is only used when T is int
map<int, char> m_map; // this is only used when T is double
queue<int> m_queue; // this is only used when T is bool
};
template<>
void A<int>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for int case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_indices[i] = true : m_indices[i] = false; }
}
template<>
void A<double>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for double case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_map[i] = 'e' : m_map[i] = 'o'; }
}
template<>
void A<bool>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for bool case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_queue.push(1) : m_queue.push(0); }
}
As you can see, there are several methods that are common regardless the T type and involves the use of the m_v vector (methods: v(), isValid(), operator[]). However, there are also other methods (method1()) that have a specific implementation depending on T type, and also requires the use of specific data structures depending on this type (queues, maps, vectors). I see very very ugly the definition of queues, maps, vectors, etc in the class although if they are only used in concrete cases depending the T type.
Option 2: The other alternative:
class A
{
public:
A() {}
int components() const { return m_components; }
double value() const { return m_value; }
virtual void method1() == 0;
protected:
int m_components;
double m_value;
};
/***** Derived A for int case ****/
class Aint : public A
{
public:
Aint() {}
vector<int> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
int operator [] (const int i) const { return m_v[i]; }
int& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<int> m_v;
vector<bool> m_indices;
};
void Aint::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_indices[i] = true : m_indices[i] = false; }
}
/***** Derived A for double case ****/
class Adouble : public A
{
public:
Adouble() {}
vector<double> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
double operator [] (const int i) const { return m_v[i]; }
double& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<double> m_v;
map<int, char> m_map;
};
void Adouble::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_map[i] = 'e' : m_map[i] = 'o'; }
}
/***** Derived A for bool case ****/
class Abool : public A
{
public:
Abool() {}
vector<bool> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
bool operator [] (const int i) const { return m_v[i]; }
bool& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<bool> m_v;
queue<int> m_map;
};
void Abool::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_queue.push(1) : m_queue.push(0); }
}
As you can see, in this case the type specific data structures (queues, maps, etc) are only defined for their required cases (not in the general class template of the Option 1). But, now the m_v vector should be defined at each derived class due to its specific type. Hence, the stuff for accesing and manipulating the vector should be replicated always in all the derived classes although they are always the same (methods v(), isValid(), operator[], etc). It also seems non-well designed.
What is the best design for that purpose?
Thank you

set<> class, when I insert into the class, it doesn't accept my < operator

class Tuple
{
private:
vector<string> values;
public:
Tuple(vector<Parameter> newValues)
{
for(int i = 0; i < newValues.size(); i++)
{
string val = newValues[i].getValue();
values.push_back(val);
}
}
Tuple(vector<string> newAttributes)
{
values = newAttributes;
}
~Tuple()
{
}
bool operator < (Tuple &tup)
{
if(values < tup.getStringVec())
return true;
return false;
}
bool operator <= (Tuple &tup)
{
if(values <= tup.getStringVec())
return true;
return false;
}
bool operator > (Tuple &tup)
{
if(values > tup.getStringVec())
return true;
return false;
}
bool operator >= (Tuple &tup)
{
if(values >= tup.getStringVec())
return true;
return false;
}
};
class Relation
{
private:
set<Tuple> tupleSet;
public:
Relation():
{
}
~Relation()
{
}
void addToTupleSet(Tuple newTuple)
{
tupleSet.insert(newTuple); //<<this causes the problem
}
};
The default comparator for std::set uses std::less<T>, which requires the object be exposed to an operator < of some form. This will be generally one of two forms:
A free function, like this:
bool operator <(const Tuple& arg1, const Tuple& arg2);
or a member function, like this:
class Tuple
{
public:
bool operator <(const Tuple& arg) const
{
// comparison code goes here
}
};
If you don't want to implement operator < just for use in a std::set you can certainly implement your own binary comparator type directly and use that as the comparator alternative to std::less<T>. Whether you do is your call, and a different solution to a different question (i.e. how to do that, which Niyaz covered in another answer).
Your code, slightly modified to not suck in namespace std and using references where appropriate (you may want to take a look at those, btw, as they will significantly reduce your time spent copying data to and fro).
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <set>
// I added this, as your source included no such definition
class Parameter
{
public:
Parameter(const std::string s) : s(s) {}
const std::string& getValue() const { return s; }
private:
std::string s;
};
class Tuple
{
private:
std::vector<std::string> values;
public:
Tuple(const std::vector<Parameter>& newValues)
{
for(auto val : newValues)
values.push_back(val.getValue());
}
Tuple(const std::vector<std::string>& newAttributes)
: values(newAttributes)
{
}
// note const member and parameter. neither the passed object nor
// this object should be modified during a comparison operation.
bool operator < (const Tuple &tup) const
{
return values < tup.values;
}
};
class Relation
{
private:
std::set<Tuple> tupleSet;
public:
void addToTupleSet(const Tuple& tup)
{
tupleSet.insert(tup);
}
};
int main(int argc, char *argv[])
{
Tuple tup({"a","b","c"});
Relation rel;
rel.addToTupleSet(tup);
return 0;
}
Use below for operator "<"
bool operator < (const Tuple &tup) const
{
/*if(values < tup.getStringVec())
return true;*/ //getStringVec undefined, so comment out temporarily
return false;
}
Your predicate must provide operator like:
struct Compare
{
bool operator() ( const T1& lhs, const T2& rhs )
{
// here's the comparison logic
return bool_value;
}
};
and specify it as the set's comparator:
std::set<Tuple, Compare> tupleSet;

generic lookup method?

I'd like a generic method for retrieving the data from a vector.
I have a the following class and vector:
class myClass
{
public:
myClass(int myX, float myZ, std::string myFoo)
: x ( myX )
, z ( myZ )
, foo ( myFoo )
{
}
myClass()
{
}
int x;
float z;
std::string foo;
} ;
std::vector < myClass > myVector;
(The complete code can be seen here: http://codepad.org/iDD1Wme5 )
In this example I would like to be able to retrieve objects in the vector based on the "z" or "foo" members without having to write another 2 functions similar to "FindDataById".
Is that possible?
You can use a template and pointer to member.
typedef vector<myClass> myVector;
template<typename T>
bool FindDataById(const T &id, T myClass::* idMember, myClass &theClass,
const myVector &theVector)
{
for(myVector::const_iterator itr = theVector.begin(); itr != myVector.end();
++itr){
if((*itr).*idMember == id){
theClass = *itr;
return true;
}
return false;
}
Then call using, e.g.,
FindDataById(string("name"), &myClass::foo, theClass, theVector)
FindDataById(5, &myClass::x, theClass, theVector)
FindDataById(5.25f, &myClass::z, theClass, theVector)
Or, go with the find_if idea:
template<typename T>
struct Finder {
T val_;
T myClass::* idMember_;
Finder(T val, T myClass::* idMember) : val_(val), idMember_(idMember) {}
bool operator()(const myClass &obj) { return obj.*idMember_ == val_; }
};
And use:
find_if(theVector.begin(), theVector.end(), Finder<string>("name", &myClass::foo))
find_if(theVector.begin(), theVector.end(), Finder<int>(5, &myClass::x))
find_if(theVector.begin(), theVector.end(), Finder<float>(3.25f, &myClass::z))
See the answer of MSalters for a way to deduce the template argument automatically.
std::find_if has already been suggested, but without a code sample, so here's a more detailed version:
Define two functors to identify the object you're interested in:
struct z_equals {
z_equals(float z) : z(z) {}
bool operator()(const myClass& obj)
return z == obj.z;
}
float z;
};
struct foo_equals {
foo_equals(const std::string& foo) : foo(foo) {}
bool operator()(const myClass& obj)
return foo == obj.foo;
}
const std::string& foo;
};
And now, to search for elements where z == 42.0f, or foo == "hello world":
std::find_if(myVector.begin(), myVector.end(), z_equals(42.0f));
std::find_if(myVector.begin(), myVector.end(), foo_equals("hello world"));
You can use functors and pass it to your lookup method. That I mean is, define class which will overload bool operator( vectorElement element) and within this operator you will choose method how do you want to lookup the values.
template <typename T>
class ILookUp
{
bool operator( vector<T> elem)
{
if (elem == something)
return true;
false;
}
};
class VectorStorage
{
std::vector<Elements> lookup( ILookUp<Elements> lookup)
{
.....
if ( lookup(elem))
{
//add element to vector or whatever.
}
.....
return result;
}
.....
}
It might be worth taking a look at std::find defined in algorithm and boost::lambda
Without lambda's you'd need to write some predicates, or at least instantiate them:
template
struct member_select : public std::unary_function
{
T t;
T U::* m_u;
member_select(T const& t, T U::* m_u) : t(t), m_u(m_u) {}
bool operator()(U const& u) const { return u.*m_u == t; }
};
template
member_select make_member_select(T const& t, T U::* m_u)
{
return member_select(t, m_u);
}
Use: std::find_if(..., make_member_select("x", &myClass::foo));