This is a contrived example, I know it doesn't make sense in this context. In my real case, v contains a larger class, and I can't refactor v due to other dependencies in the code base. Also, in the real case I'm not using std::set but it simplifies the example. Here are two example classes A and B that I know don't work, and I do understand why, but hopefully will illustrate what I'm trying to do:
#include <set>
#include <vector>
using namespace std;
struct A
{
A(initializer_list<float> init) : v(init)
{
for(size_t i = 0; i < init.size(); i)
{
s.insert(i);
}
}
struct Less
{
Less(const vector<float>& v) : v(v) {};
bool operator()(size_t i, size_t j)
{
return v[i] < v[j];
}
const vector<float>& v;
};
vector<float> v;
set<size_t, Less> s;
};
struct B
{
B(initializer_list<float> init) : v(init)
{
for(size_t i = 0; i < init.size(); i)
{
s.insert(i);
}
}
template<const vector<float>& v>
struct Less
{
bool operator()(size_t i, size_t j)
{
return v[i] < v[j];
}
};
vector<float> v;
set<size_t, Less<v>> s;
};
int main()
{
A a = {1., 2., 3.};
B b = {1., 2., 3.};
}
In both cases s contains indicies that refer to elements in v, and Less is trying to compare the values in v using those indices. Is there a way to do this that I'm not seeing?
CodePudding user response:
Your A approach is almost correct. It just needs 2 fixes:
bool operator()(size_t i, size_t j)should beconst.smust have a configured functor passed to it during construction.
struct A
{
A(initializer_list<float> init) : v(init), s(v)
{
for(size_t i = 0; i < init.size(); i)
{
s.insert(i);
}
}
// These must be manually defined if you need them, the default
// ones won't be correct.
A(const A&) = delete;
A& operator=(const A&) = delete;
struct MyLess
{
MyLess(const vector<float>& v) : v(v) {};
bool operator()(size_t i, size_t j) const
{
return v[i] < v[j];
}
const vector<float>& v;
};
vector<float> v;
set<size_t, MyLess> s;
};
I'm using unordered_map so maybe your idea will still work?
Yes, the same principle applies to std::unordered_set. You just have to pass in both hash and key_equal during construction. Check out the documentation to identify the correct constructor to invoke.
