Comparator that requires access to private members of class - c++

Basic structure of my code is
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void doSomething(){
std::sort(_n.begin(), _n.end(), Comp);
}
...
};
But I get
error: no matching function for call to
‘sort(std::vector<unsigned int>::iterator,
std::vector<unsigned int>::iterator, <unresolved overloaded function type>)
How can I resolve this problem WITHOUT COPYING THE VECTORS? (because these vectors are very very big 17179508 strings to be precise).

std::sort expects a binary predicate taking two ints in this case. A member function takes an implicit first parameter, so in all Foo::Comp takes three parameters. You could pass a non-member function, or a static member function, but neither of these would have access to Foo's data members. The simples way is to use std::bind to bind this to the first parameter of the member function:
#include <functional> // for std::bind
#include <vector>
#include <algorithm>
class Foo{
vector<string> _lines;
vector<int> _n;
public:
...
bool Comp(int i, int j){
return something that depends on _lines;
}
...
void sort(){
using namespace std::placeholders;
std::sort(_n.begin(), _n.end(), std::bind(Comp, this, _1, _2));
}
...
};

The most obvious initial suggestion is to aggregate your int and string into a struct or std::pair, have a single vector with the aggregate in it, and then sort that vector of aggregates.
But if the two vectors are in fact independent, I would suggest using an external predicate, instead of your Comp method:
struct Comp
{
explicit Comp(vector<string>& lines) : lines_(lines) { }
bool operator()(int i, int j) const
{
return something that depends on lines_;
}
vector<string>& lines_;
};
Then call it:
void doSomething()
{
std::sort(_n.begin(), _n.end(), Comp(_lines));
}

What about using your object as the comparator itself. This compiles on gcc 4.6:
class Foo{
std::vector<std::string> _lines;
std::vector<int> _n;
public:
bool operator()(int i, int j){
return false;
}
void doSomething(){
std::sort(_n.begin(), _n.end(), *this);
}
};
Edit:
Turns out that was not such a good idea, copying an object with 17M strings would incur a huge penalty. A nested class, taking a pointer, could be used instead. That would also allow us to have different comparators:
class Foo
{
std::vector<std::string> _lines;
std::vector<int> _n;
class Bar
{
public:
Bar( const Foo * foo ) : _foo( foo ) {}
bool operator()( int i, int j )
{
act on _foo->_lines
}
private:
const Foo * _foo;
};
public:
void doSomething(){
std::sort(_n.begin(), _n.end(), Bar(this));
}
};

Related

Are there any alternatives to making const version of class?

In C++ I'm often facing a situation when I need to prepare const and non-const version of class in analogy to const_iterator and iterator from standard library.
class const_MyClass
{
public:
const_MyClass(const int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
private:
const int * m_arr;
}
class MyClass
{
public:
MyClass(int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
void modify(int i); //modify m_arr
private:
int * m_arr;
}
The problem with this is that I need to repeat whole code of const_MyClass in MyClass and distribute any changes in API to both classes. Thus sometimes I inherit const_MyClass and do some const_casts, which also isn't perfect and pretty solution. Still when I want to pass const_MyClass instance by reference it looks moronic:
void func(const const_MyClass & param)
Instance param is marked with two "consts", and it has only const methods...
This is where const constructors would be handy, but are there any existing alternatives?
Some use examples to explain problem better:
//ok to modify data
void f(int * data)
{
MyClass my(data);
my.modify();
...
}
//cant modify data, cant use MyClass
void fc(const int * data)
{
const_MyClass my(data);
int i = my.method();
...
}
You can make a template class to act as a base, like this:
template<typename T>
class basic_MyClass
{
public:
basic_MyClass(T * arr) :m_arr(arr) {}
int method() const; //does something with m_arr without modifying it
private:
T * m_arr;
};
Then, for your const version, since it doesn't add anything, you can just use a typedef:
typedef basic_MyClass<const int> const_MyClass;
For your non-const version, you can inherit:
class MyClass : public basic_MyClass<int>
{
public:
using basic_MyClass::basic_MyClass; // inherit all the constructors
void modify(int i); //modify m_arr
};
Have you considered simply tracking two pointers and raising exceptions from the mutable operations when no mutable value is available? Maybe an example will help describe what I am thinking of.
class MyClass
{
public:
MyClass(int *mutable_data):
m_mutable_view(mutable_data), m_readonly_view(mutable_data)
{
}
MyClass(const int *immutable_data):
m_mutable_view(NULL), m_readonly_view(immutable_data)
{
}
int retrieve_value(int index) {
return m_readonly_view[index];
}
void set_value(int index, int value) {
require_mutable();
m_mutable_view[index] = value;
}
protected:
void require_mutable() {
throw std::runtime_error("immutable view not available");
}
private:
const int *m_readonly_view;
int *m_mutable_view;
};
The idea is pretty simple here - use a sentinel value to indicate whether modifications are possible or not instead of depending on the type system to do that for you. Personally, I would think about doing the inheritance based approach that #BenjaminLindley suggested but I wanted to present a slightly different solution that might not have occurred to you.
After talk with Neil Kirk I realized what I was doing wrong. I started by separating data from logic as he suggested.
This attempt resulted in two classes MyClassPtr and const_MyClassPtr. They only provide functions for data access (like iterators) and may look like that:
class const_MyClassPtr
{
public:
const_MyClassPtr(const int * arr);
int operator [](int i) const;
const int * ptr() const;
private:
const int * m_arr;
}
class MyClassPtr
{
public:
MyClassPtr(int * arr);
int operator [](int i) const;
int & operator [](int i);
const int * ptr() const;
int * ptr();
//promotion to const pointer
const_MyClassPtr () const {return const_MyClassPtr(m_arr);}
private:
int * m_arr;
}
Now it is clear that objects of these classes should be treated like pointers, so when I use them as function parameters I pass them by value!
void func(const_MyClassPtr param) //instead of void func(const const_MyClass & param)
To provide methods I have created MyClassOp class template and used static polymorphism.
template <class DERIVED>
class MyClassOp
{
public:
const DERIVED & derived() const {return static_cast<const DERIVED &>(*this)}
DERIVED & derived() {return static_cast<DERIVED &>(*this)}
int method() const; //operates on derived() const
void modify(int i); //operates on derived()
}
MyClassOp is a collection of methods. It does not have state. In general it is a trait. To make these methods accessible I overloaded -> and * operators
class const_MyClassPtr : private MyClassOp<const_MyClassPtr>
{
public:
const MyClassOp<MyClassPtr> * operator ->() const {return this;}
const MyClassOp<MyClassPtr> & operator *() const {return *this;}
...
}
class MyClassPtr : private MyClassOp<MyClassPtr>
{
public:
MyClassOp<MyClassPtr> * operator ->() {return this;}
MyClassOp<MyClassPtr> & operator *() {return *this;}
...
}
This works O.K., but is a bit cumbersome. If I have for example equality operator I need to write something like *myptr1 == myptr2 to compare values kept by two MyClassPtr objects (it's easy to make a mistake and compare myptr1 == myptr2 or expect that something like *myptr1 == *myptr2 could work). Also when I have allocating type:
class MyClass : public MyClassOp<MyClass>
{
MyClass(int x, int y, int z);
...
int m_arr[3];
}
I would want to be able to use temporaries as function arguments.
void f(const_MyClassPtr my);
//use temporary when calling f()
f(MyClass(1, 2, 3));
I can do this by providing conversion operators or conversion constructors (that convert MyClass to const_MyClassPtr). But then const_MyClassPtr behaves more like reference than pointer. If iterators are generalization of pointers then why one could not imitate reference? Therefore I divided MyClassOp into two parts (const and non const) and replaced -> and * operators implemented by const_MyClassPtr and MyClassPtr with public inheritance and changed their names to ressemble reference. I ended up with following structures.
MyClassOp : public const_MyClassOp
const_MyClassRef : public const_MyClassOp<const_MyClassRef>
MyClassRef : public MyClassOp<MyClassRef>
MyClass : public MyClassOp<MyClass>
However const_MyClassRef and MyClassRef are not perfect generalization of reference as it impossible to imitate some of C++ reference properties, so Ref suffix is there to denote reference-like structure.
Maybe you can find some hints in effective c++ item 4 "Avoid duplication in const and non-const Member function"
I may summarize like following ( it makes you avoid code duplication even if using somewhat ugly cast ):
struct my_class
{
my_class(int x):_x(x){};
const int& method(void) const;
int& method(void);
int _x;
};
const int& my_class::method(void) const //func for const instance
{
return _x;
}
int& my_class::method(void) //func for normal instance
{
return const_cast<int& >(static_cast<const my_class& >(*this).method()) ;
}
int main()
{
my_class a(1);
const my_class b(2);
a.method() = 5;
cout << a.method() << endl;
//b.method() = 4; //b is const, wont compile
cout << b.method() << endl;
return 0;
}

operator() from virtual class not recognized by remove_if

I have vector of objects and a vector of criteria to filter by. Inspired by Moo-Juice from this post, I wrote such a code:
#include <algorithm>
#include <string>
#include <memory>
#include <vector>
struct Token {
char code;
int val;
Token(char c,int a) : code(c),val(a) {}
};
class FilterBase {
public:
virtual bool operator()(const std::shared_ptr<Token> p) =0;
};
class ByCode : public FilterBase {
public:
ByCode( char c) : code_(c) {}
virtual bool operator()(const std::shared_ptr<Token> p) {
return code_ == p->code;
}
private:
unsigned char code_;
};
int main() {
std::vector<std::shared_ptr<FilterBase>> filters;
filters.push_back(std::make_shared<ByCode>('A'));
filters.push_back(std::make_shared<ByCode>('B'));
std::shared_ptr<Token> p = std::make_shared<Token>('M', 20);
std::vector<std::shared_ptr<Token>> tokens;
tokens.push_back(p);
filters[0]->operator ()(p);
for (const std::shared_ptr<FilterBase> fi : filters) {
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
}
}
But unfortunately it does not compile, because parameter type 'FilterBase' is an abstract class. Well I know it is, I just thoght the virtual keyword would make it working...
Replace:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), *fi), tokens.end());
with:
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), std::ref(*fi)), tokens.end());
remove_if takes its functor by-value, which causes your *fi to be sliced into an instance of the base class, which has a pure virtual object. Things go poorly.
std::ref has an overloaded operator() which should invoke the virtual operator() of *fi if MSVC didn't screw things up (for example, if it invokes the operator the wrong way).
If this fails, you can write your own adapter:
template<typename T>
struct callable_by_ref {
T* t;
template<typename... Args>
auto operator(Args&&...args) const ->
decltype( std::declval<T&>()(std::declval<Args&&>()...) )
{
return (*t)(std::forward<Args>(args)...);
}
};
template<typename T>
callable_by_ref< typename std::remove_reference<T>::type >
call_by_ref( T&& t ) {
return {&t};
}
which should solve your problem even if std::ref does not.
tokens.erase(std::remove_if(tokens.begin(), tokens.end(), call_by_ref(*fi)), tokens.end());
What I am doing:
The callable_by_ref is basically a quick perfect forwarder with a half-functional std::reference_wrapper implementation on top of it. call_by_ref does type deduction for you to create such an object.

std::vect sorting with member variable

I'm stuck with this piece of code:
class MyObject
{
public:
int value;
}
class MyClass
{
private:
btAlignedObjectArray<MyObject*> m_objects;
public:
int comp (MyObject *a, MyObject *b)
{
return calculateTheNewValue(a->value) < calculateTheNewValue(b->value);
}
void doSort()
{
m_objects.quickSort(comp);
}
//edit: this member function is needed to do the sorting
int calculateTheNewValue(int v)
{
// do some calculation using other members variables, not necessarily m_objects
}
};
It doesn't compile because comp is a non static member function.
comp cant be static, because it needs to access the member variable m_objects.
Also it would defeat the encapsulation of m_objects to have a static function and call it like this
MyClass::doSort(myClass.m_objects)
Edit
This is the declaration of btAlignedObjectArray
http://bulletphysics.org/Bullet/BulletFull/btAlignedObjectArray_8h_source.html
Line 365 has the declaration or quicksort
If you need to make comp into a binary function, then wrap it in a functor. If you can use C++11, then use a lambda:
m_objects.quickSort([&](MyObject * lhs, MyObject * rhs) {
return this->comp(lhs,rhs)
});
If you can't use C++11, then make a functor class with similar behavior.
struct compare
{
MyObject & obj_;
compare(MyObject& obj) :obj_(obj) {}
bool operator()(MyObject * lhs, MyObject * rhs) const {
return obj_.comp(lhs,rhs);
}
};
...
void doSort()
{
m_objects.quicksort(compare(*this));
}

pointer to const member function typedef

I know it's possible to separate to create a pointer to member function like this
struct K { void func() {} };
typedef void FuncType();
typedef FuncType K::* MemFuncType;
MemFuncType pF = &K::func;
Is there similar way to construct a pointer to a const function? I've tried adding const in various places with no success. I've played around with gcc some and if you do template deduction on something like
template <typename Sig, typename Klass>
void deduce(Sig Klass::*);
It will show Sig with as a function signature with const just tacked on the end. If to do this in code it will complain that you can't have qualifiers on a function type. Seems like it should be possible somehow because the deduction works.
You want this:
typedef void (K::*MemFuncType)() const;
If you want to still base MemFuncType on FuncType, you need to change FuncType:
typedef void FuncType() const;
typedef FuncType K::* MemFuncType;
A slight refinement showing how to do it without a typedef.
In a deduced context like the following, you can't use a typedef.
template <typename Class, typename Field>
Field extract_field(const Class& obj, Field (Class::*getter)() const)
{
return (obj.*getter)();
}
applied to some class with a const getter:
class Foo {
public:
int get_int() const;
};
Foo obj;
int sz = extract_field(obj, &Foo::get_int);
Another more direct way to do it (avoiding using and typedefs) is this:
#include <iostream>
class Object
{
int i_;
public:
int j_;
Object()
: Object(0,0)
{}
Object(int i, int j)
: i_(i),
j_(j)
{}
void printIplusJplusArgConst(int arg) const
{
std::cout << i_ + j_ + arg << '\n';
}
};
int main(void)
{
void (Object::*mpc)(int) const = &Object::printIplusJplusArgConst;
Object o{1,2};
(o.*mpc)(3); // prints 6
return 0;
}
mpc is a const method pointer to Object.

C++ refactor common code with one different statement

I have two methods f(vector<int>& x, ....) and g(DBConn& x, ....)
where the (....) parameters are all identical.
The code inside the two methods are completely identical except for one statement
where we do different actions based on the type of x:
in f(): we do x.push_back(i)
in g(): we do x.DeleteRow(i)
What is the simplest way to extract the common code into one method and yet
have the two different statements?
I am thinking of having a templated functor that overloads operator () (int a) but that seems overkill.
common_function(....)
{
}
f(vector<int>x,... )
{
x.push_back(i);
common_f(...);
}
g(DBConn& x, ....)
{
x.DeleteRow(i);
common_f(...);
}
You could write a simple adapter with two implementations, each calling the desired method of a different class.
class MyInterface {
public:
virtual doIt(int i) = 0;
}
class VectorImp : public MyInterface {
public:
vector<int>& v;
VectorImp(vector<int>& theVector) : v(theVector) {}
doIt(int i) { x.push_back(i); }
}
class DbImp : public MyInterface {
public:
DBConn& c;
VectorImp(DBConn& conn) : c(conn) {}
doIt(int i) { c.DeleteRow(i); }
}
template<class T>
struct Adapter;
template<>
struct Adapter<vector<int> >
{
static void execute(vector<int> &x, int i)
{
x.push_back(i);
}
};
template<>
struct Adapter<DBConn>
{
static void execute(DBConn &x, int i)
{
v.DeleteRow(i);
}
};
template<class T>
void f(T &t, ...)
{
...
Adapter<T>::execute(t, i);
...
}
OR:
template<class T>
struct adapter_traits;
template<>
struct adapter_traits<vector<int> >
{
typedef void (vector<int>::*PMF)(int);
static const PMF pmf = &vector<int>::push_back;
}
template<>
struct adapter_traits<DBConn>
{
typedef void (DBConn::*PMF)(int);
static const PMF pmf = &DBConn::DeleteRow;
}
template<class T>
void f(T &t, ...)
{
...
(t.*adapter_traits<T>::pmf)(i);
...
}
NOTE: I might have some syntax wrong but you get the idea.
Yet another idea:
template<class T>
void f(T &t, void (T::*p)(int), ...)
{
...
(t.*p)(i);
}
void g()
{
DBConn x;
vector<int> y;
f(x, &DBConn::DeleteRow, ...);
f(y, &vector<int>::push_back, ...);
}
Classic case for a functor:
#include <vector>
#include <DBConn.h>
// T: The type of the object that is to be manipulated.
// A: The type of the object that will do the manipulating
// This may be a functor object or a function pointer.
//
// As this is a template function the template parameters will
// be deduced by the compiler at compile time.
template<typename T,typename A>
void action(T& obj,A const& action/*,....*/)
{
// Do Stuff
action(obj,5);
// Do more Stuff
}
// Functor object
struct MyVectorAction
{
// Just defines the operator()
// Make sure it is a const method.
// This does the unique bit of code. The parameters should be what you pass into action
void operator()(std::vector<int>& data,int val) const {data.push_back(val);}
};
void f(std::vector<int>& x)
{
action(x,MyVectorAction()/*.... Params ....*/);
}
struct MyDBConnAction
{ void operator()(DBConn& data,int val) const {data.DeleteRow(val);} };
void g(DBConn& x)
{
action(x, MyDBConnAction());
}
int main()
{
std::vector<int> x;
f(x);
}
You could make a function that has the parameters of what you call (...), and this function can implement the logic that is the same in f() and g(). You could then change the implementation of f() and g() to call this new function instead of duplicating the logic. Be careful though if you're doing something duplicated before and after your unique lines. You may need two functions in that case. At any rate I think this would be preferable to having duplicated blocks of code.