I want to create std::map in STL, but the comparer depends some dynamic value which is available only at runtime.. How can I make this? For example, I want something looks like std::map<int, int, Comp(value1, value2)>. value1 and value2 are not the compared number here, they are some kind of configuration numbers.
Use a functor class:
#include <map>
class Comp
{
public:
Comp(int x, int y) : x(x), y(y) {}
bool operator() (int a, int b) const { /* Comparison logic goes here */ }
private:
const int x, y;
};
int main()
{
std::map<int,float,Comp> m(Comp(value1,value2));
}
This is like a function, but in the form of a runtime object. This means it can have state, which includes runtime configuration. All you have to do is overload operator(). If you define all the member-function bodies in the class definition (as above), then the compiler will probably inline everything, so there'll be negligible performance overhead.
If you know value1 and value2 at compile-time (i.e. if they are compile-time constants), you could use a function template instead:
template <int x, int y>
bool compare(int a, int b) { /* Comparison logic goes here */ }
int main()
{
std::map<int,float,compare<value1,value2> > m;
}
Related
I'm not an advanced programmer. How can I overload the [] operator for a class that has two (or more) array/vector type variables?
class X
{
protected:
std::vector<double> m_x, m_y;
public:
double& operator[](const short &i) { return ???; }
};
What should I use for ???, or how can I do it (maybe adding other definitions?) to be able to call either variable?
Additional question: will this allow other classes of type class derived : public X access m_x and m_y for writing?
UPDATE:
Thank you everyone who answered, but I'm afraid that if I draw the line then the answer to my first question is no, and to the second yes. The longer version implies either an extra struct, or class, or plain setters/getters, which I wanted to avoid by using a simple function for all.
As it stands, the current solution is a (temporary) reference to each variable, in each class to avoid the extra X:: typing (and keep code clear), since m_x would have existed, one way or another.
you can write just a function for this, like:
double &get(unsigned int whichVector, unsigned int index)
{
return (whichVector == 0 ? m_x[index] : m_y[index]);
}
or use operator():
struct A
{
std::vector<int> a1;
std::vector<int> a2;
int operator()(int vec, int index)
{
return (vec == 0 ? a1[index] : a2[index]);
}
};
A a;
auto var = a(0, 1);
but still, this is kinda strange :) probably you should just give a const ref outside, like:
const std::vector<double> &getX() const { return m_x; }
and second question: protected will be convert into private in public inheritance (child/derived will have access to these memebers)
Assuming you want m_x and m_y indexed against the same parameter and a single return value:
struct XGetter
{
double& x;
double& y;
};
XGetter operator[](const short &i) { return { m_x[i], m_y[i] }; }
And the const overload:
struct XGetterReadOnly
{
double x;
double y;
};
XGetterReadOnly operator[](const short &i) const { return { m_x[i], m_y[i] }; }
The compiler will make a good job of optimizing away the intermediate classes XGetter and XGetterReadOnly where appropriate which maybe hard to get your head round if you're a new to C++.
If using mixin doesn't make you uncomfortable you could use tag dispatching like:
#include <utility>
#include <vector>
#include <iostream>
template <size_t I>
struct IndexedVector {
std::vector<double> v;
IndexedVector():v(10){}
};
template <size_t I>
struct tag {
int i;
};
template <size_t S, class = std::make_index_sequence<S>>
struct MixinVector;
template <size_t S, size_t... Is>
struct MixinVector<S, std::index_sequence<Is...>>: IndexedVector<Is>... {
template <size_t I>
double &operator[](tag<I> i) {
return IndexedVector<I>::v[i.i];
}
};
int main() {
MixinVector<2> mv;
mv[tag<0>{0}] = 1.0;
std::cout << mv[tag<0>{0}] << std::endl;
}
To use std::index_sequence you need however compiler supporting c++14 (you could though implement it yourself in c++11). The approach is easily expandable to any number of vectors by simple MixinVector template parameter modification.
There are many broken things, either at conceptual and design level.
Are you able to point your finger simultaneously against two distinct things? No? That's why you cannot use one index to address two distinct vector retaining their distinction.
You can do many things: whatever way to "combine" two value int one is good
by a syntactic point of view:
return m_x[i]+m_y[x] or return sin(m_x[i])*cos(m_y[i]) or return whatever_complicated_expression_you_like_much
But what's the meaning of that? The point is WHY THERE ARE TWO VECTOR IN YOUR CLASS? What do you want them to represent? What do you mean (semantically) indexing them both?
Something I can do to keep their distinction is
auto operator[](int i) const
{ return std::make_pair(m_x[i],m_y[i]); }
so that you get a std::pair<double,double> whose fist and second members are m_x[i] and m_y[i] respectively.
Or ... you can return std::vector<double>{m_x[i],m_y[i]};
About your other question: Yes, inheriting as public makes the new class able to access the protected parts: that's what protected is for.
And yes, you cam R/W: public,protected and private are about visibility, not readability and writeability. That's what const is about.
But again: what does your class represent? without such information we cannot establish what make sense and what not.
Ok, stated your comment:
you need two different funcntions: one for read (double operator[](unsigned) const) and one for write (double& operator[](unsigned) const)
If you know vectors have a known length -say 200-, that you can code an idex transforamtion like i/1000 to identify the vector and i%1000 to get the index,so that 0..199 addres the first, 1000..1199 address the second 2000..2199 address the third... etc.
Or ... you can use an std::pair<unsigned,unsigend> as the index (like operator[](const std::pair<unsigned,unsigned>& i), using i.first to identify the vector, and i.second to index into it, and then call x[{1,10}], x[{3,30}] etc.
Or ... you can chain vetor together as
if(i<m_x.size()) return m_x[i]; i-=m_x:size();
if(i<m_y.size()) return m_y[i]; i-=m_y:size();
if(i<m_z.size()) return m_z[i]; i-=m_z:size();
...
so that you index them contiguously.
But you can get more algorithmic solution using an array of vectors instead of distinct vector variables
if you have std::array<std::vector<double>,N> m; instead of m_x, m_y and m_z the above code can be...
for(auto& v: m)
{
if(i<v.size()) return v[i];
i-=v.size();
}
You can return a struct has two double
struct A{
double& x;
double& y;
A(A& r) : x(r.x), y(r.y){}
A(double& x, double& y) : x(x), y(y){}
};
class X
{
protected:
std::vector<double> m_x, m_y;
public:
A operator[](const short &i) {
A result(m_x[i], m_y[i]);
return result;
}
};
Thank for editing to #marcinj
I am trying to specialize std::unordered_map for a class X with a custom hash and a custom equality. The problem is that both the equality and hash functions do not depend only on the object(s) of class X but also on data in another (fixed) object of another class Y. Here is a toy example (with only the hash function) of what I want to do:
#include <unordered_map>
using namespace std;
struct Y {
bool b;
struct X {
size_t i;
};
size_t hash(const X &x) {
return x.i + b;
}
unordered_map<X, int, hash> mymap;
};
The problem is that the function hash in the template specialization is a method and the compiler complains ("call to non-static member function without an object argument"). What I want is that y.mymap uses y.hash(). Any way to do this?
Note that in the real code Y is also a template, in case it matters.
Thanks!
EDIT: To clarify, instead of the boolean b in my code I have a vector with data that is needed in comparing objects of type X. Some data is added when an X is created, so the vector is not constant, but the data for a given X does not change after it is added, so the hash for a given X never changes (so in a sense it depends only on X as required for a hash). The main reason I use this approach is to save memory since this data is a lot and is usually shared.
You can use function<size_t(X const&)> and e.g. bind, but as type erasure is not necessary in this case, here is a simpler solution:
struct Y {
bool b;
struct X {
size_t i;
bool operator==(X x) const {return i == x.i;}
};
size_t hash(const X &x) {
return x.i + b;
}
struct Hasher {
Y* this_;
template <typename T>
auto operator()(T&& t) const
-> decltype(this_->hash(std::forward<T>(t))) {
return this_->hash(std::forward<T>(t));
}
};
unordered_map<X, int, Hasher> mymap;
Y() : b(false),
mymap(0, {this}) {}
};
As mentioned by #dyp in the comments, you have to be careful with special member functions since we implicitly store this in mymap - i.e. the compiler-generated definitions would copy the this_ pointer. An example implementation of the move constructor could be
Y(Y&& y) : b(y.b), mymap(std::make_move_iterator(std::begin(y.mymap)),
std::make_move_iterator(std::end (y.mymap)), 0, {this}) {}
Unfortunately what you want to do is not legal. See 17.6.3.5/Table 26:
h(k) The value returned shall depend only on the argument k.
It's pretty clear that you aren't allowed to have the hash depend on a member of Y as well as X.
EDIT: Just in case you meant for b to be const in your Y class there is a solution (I didn't compile this yet, I will if I get a chance):
struct Y
{
explicit Y(bool config) : b(config), hash_(config), mymap(0, hash_) { }
const bool b;
struct X
{
size_t i;
};
struct Hash
{
explicit Hash(bool b) : b_(b) { }
size_t operator()(const X& x) const
{
return x.i + b_;
}
private:
bool b_;
};
Hash hash_;
unordered_map<X, int, Hash> mymap;
};
This might sound like a stupid problem but I wondered for a long time is there a better way that this:
struct X
{
int a;
int b;
};
bool sortComp(const X first, const X second)
{
if (first.a!=second.a)
return (first.a<second.a);
else
return (first.b<second.b);
}
class setComp
{
public:
bool operator() (const X first, const X second) const
{
if (first.a!=second.a)
return (first.a<second.a);
else
return (first.b<second.b);
}
};
int main()
{
vector<X> v;
set<X, setComp> s;
sort(begin(v), end(v),sortComp);
}
As you see I implement the same functionality twice, once for sorting, and once for implicit sorting in the set. Is there a way to avoid code duplication?
Sure, just choose one of both and change the call of the other.
// choosing the function object
sort(begin(v), end(v), setComp()); // create setComp, sort will call operator()
// choosing the function
set<X, bool(*)(const X, const X)> s(sortComp); // pass function pointer
I personally would recommend the functor version.
I know I cannot derive from an int and it is not even necessary, that was just one (non)solution that came to my mind for the problem below.
I have a pair (foo,bar) both of which are represented internally by an int but I want the typeof(foo) to be incomparable with the typeof(bar). This is mainly to prevent me from passing (foo,bar) to a function that expects (bar, foo). If I understand it correctly, typedef will not do this as it is only an alias. What would be the easiest way to do this. If I were to create two different classes for foo and bar it would be tedious to explicitly provide all the operators supported by int. I want to avoid that.
As an alternative to writing it yourself, you can use BOOST_STRONG_TYPEDEF macro available in boost/strong_typedef.hpp header.
// macro used to implement a strong typedef. strong typedef
// guarentees that two types are distinguised even though the
// share the same underlying implementation. typedef does not create
// a new type. BOOST_STRONG_TYPEDEF(T, D) creates a new type named D
// that operates as a type T.
So, e.g.
BOOST_STRONG_TYPEDEF(int, foo)
BOOST_STRONG_TYPEDEF(int, bar)
template <class Tag>
class Int
{
int i;
public:
Int(int i):i(i){} //implicit conversion from int
int value() const {return i;}
operator int() const {return i;} //implicit convertion to int
};
class foo_tag{};
class bar_tag{};
typedef Int<foo_tag> Foo;
typedef Int<bar_tag> Bar;
void f(Foo x, Bar y) {...}
int main()
{
Foo x = 4;
Bar y = 10;
f(x, y); // OK
f(y, x); // Error
}
You are correct, that you cannot do it with typedef. However, you can wrap them in a struct-enum pair or int encapsuled inside struct.
template<int N>
struct StrongType { // pseudo code
int i;
StrongType () {}
StrongType (const int i_) : i(i_) {}
operator int& () { return i; }
StrongType& operator = (const int i_) {
i = i_;
return *this;
}
//...
};
typedef StrongType<1> foo;
typedef StrontType<2> bar;
C++0x solution:
enum class foo {};
enum class bar {};
Can you use templates (or the like) in C++ to specify which operation is done in a function?
I don't know how to explain it more clearly, so I'll show you how it could be (but isn't) done in code:
template <operator OPERATION> int getMaxOrMin(int a, int b) {
return a OPERATION b ? a : b;
}
where finding the maximum or the minimum of a or b would be (this is where my pseudo-syntax gets a little confusing, bear with me):
int max = getMaxOrMin< > > (a, b);
int min = getMaxOrMin< < > (a, b);
I know that's not how to do it at all (because it doesn't even syntactically make sense), but I hope that clarifies the type of thing I want to do.
The reason behind me wondering this is I'm making a PriorityQueue implementation, and it would be nice to easily switch between the backing being a max-heap or a min-heap on the fly without copying and pasting code to make two different classes.
I know I could do it with a macro, but the only way I'd know how to do that would give me either a max-heap or a min-heap, but not both in the same compilation. I'm probably overlooking a way, though.
Do what std::map and friends do: Take a comparison function/functor as your template parameter. See std::less and std::greater.
Do remember that the standard library already has a well developed and debugged priority queue that you can use with an arbitrary comparison function.
Yes but you need to define it like a functor:
template <typename OPERATION>
int getMaxOrMin(int a, int b)
{
OPERATION operation;
return operation(a, b) ? a : b;
}
Now you can use it like this:
struct myLess
{
bool operator()(int a,int b) const { return a < b; }
}
struct myGreat
{
bool operator()(int a,int b) const { return a > b; }
}
void code()
{
int x = getMaxOrMin<myLess>(5,6);
int y = getMaxOrMin<myGreat>(5,6);
}
That seems like a lot of work. But there are a lot of predefined functors in the standard. On this page scroll down to "6: Function Objects".
For your situation there is:
std::less
std::greater
So the code becomes:
template <typename OPERATION>
int getMaxOrMin(int a, int b)
{
OPERATION operation;
return operation(a, b) ? a : b;
}
void codeTry2()
{
int x = getMaxOrMin<std::less<int> >(5,6);
int y = getMaxOrMin<std::greater<int> >(5,6);
}