partial_sort and smart pointers - c++

I have a SetPartitionVector class which is derived from vector<SetPartition>. I'd like to partial_sort this vector using a custom comparison function but I have an error at compilation.
bool ScalableSummary::featuresDistComp(SetPartition cluster1, SetPartition cluster2){
return (segmentClusters.AverageSOD(cluster1) > segmentClusters.AverageSOD(cluster2));
}
void ScalableSummary::selectLeastConsensualFeatures(const int p){
partial_sort(segmentClusters.begin(), segmentClusters.begin() + p, segmentClusters.end(), featuresDistComp);
}
segmentClusters is a member of ScalableSummary of type SetPartitionVector which was filled this way :
SetPartition_ptr cluster;
...
segmentClusters.push_back(*cluster);
SetPartition_ptr is a smart pointer defined like this :
typedef boost::shared_ptr<SetPartition> SetPartition_ptr;
This is the error I get from the compiler :
g++ -o ScalableSummary.o -c ScalableSummary.cpp -Iinclude -Wall -g
ScalableSummary.cpp: In member function ‘void ScalableSummary::selectLeastConsensualFeatures(int)’:
ScalableSummary.cpp:56:108: erreur: no matching function for call to ‘partial_sort(std::vector<SetPartition>::iterator, __gnu_cxx::__normal_iterator<SetPartition*, std::vector<SetPartition> >, std::vector<SetPartition>::iterator, <unresolved overloaded function type>)’
ScalableSummary.cpp:56:108: note: candidates are:
/usr/include/c++/4.6/bits/stl_algo.h:5240:5: note: template<class _RAIter> void std::partial_sort(_RAIter, _RAIter, _RAIter)
/usr/include/c++/4.6/bits/stl_algo.h:5279:5: note: void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<SetPartition*, std::vector<SetPartition> >, _Compare = bool (ScalableSummary::*)(SetPartition, SetPartition)]
/usr/include/c++/4.6/bits/stl_algo.h:5279:5: note: no known conversion for argument 4 from ‘<unresolved overloaded function type>’ to ‘bool (ScalableSummary::*)(SetPartition, SetPartition)’

The function object you pass to std::partial_sort needs to be either a callable object, or a function pointer. To make a function pointer you nedd to use the address-of operator &, just like when you make a pointer out of any other variable:
partial_sort(..., &featuresDistComp);
// ^
// |
// Note address-of operator here
Also, I hope your function is marked as static? You can't use non-static member functions as ordinary function pointers. The reason is that all non-static member functions have a hidden first arguments that is the this pointer inside the function. So either make sure the function is static or use e.g. std::bind:
using namespace std::placeholders; // for _1, _2, _3...
partial_sort(..., std::bind(&ScalableSummary::featuresDistComp, this, _1, _2));

Related

using comparing function

I have this function
std::vector <std::vector <int> > puddles;
std::set <int> is_checked;
size_t M, N;
bool v_compare(int a, int b){
return puddles[(a-a%M)/M][a%M] < puddles[(b-b%M)/M][b%M];
}
and I want to find the set element which corresponds to the minimal value in puddles (I use i*M+j as a key in the set). So I am trying to use my function as a predicate for min_element
close(*std::min_element(is_checked.begin(), is_checked.end(), v_compare));
but I got this error
:113:82: error: no matching function for call to 'min_element(std::set<int>::iterator, std::set<int>::iterator, <unresolved overloaded function type>)'
:113:82: note: candidates are:
/usr/include/c++/4.6/bits/stl_algo.h:6173:5: note: template<class _FIter> _FIter std::min_element(_FIter, _FIter)
/usr/include/c++/4.6/bits/stl_algo.h:6201:5: note: _FIter std::min_element(_FIter, _FIter, _Compare) [with _FIter = std::_Rb_tree_const_iterator<int>, _Compare = bool (TFlood::*)(int, int)]
/usr/include/c++/4.6/bits/stl_algo.h:6201:5: note: no known conversion for argument 3 from '<unresolved overloaded function type>' to 'bool (TFlood::*)(int, int)'
There is a difference between a pointer to function and a pointer to member function. A class member which is not static gets you a pointer to member function. But std::min_element only accepts a pointer to function or other callable type, and a pointer to member function doesn't qualify since it can't be called without a pointer or reference to a class object. And as you found, if you try making the function a static member, then it can't get at the member M. (Maybe puddles too, if that's also a member.)
It looks like you're using g++ 4.6, which supports lambdas. So the easiest solution is:
close(*std::min_element(is_checked.begin(), is_checked.end(),
[this](int a, int b) { return puddles[a/M][a%M] < puddles[b/M][b%M]; }));
(I got rid of the subtractions, since division of integer types always rounds toward zero, so (a-(a%M))/M is always the same result as a/M.) Make sure you use the -std=c++0x compiler flag. The lambda magic takes care of "capturing" the this pointer for later use by the comparison object.

Custom Compare function for std::binary_search

Is there any problem with this code?
bool Spellcheck::smart_comp(string value, string key){
return true;
}
void func(){
std::string aprox_key = "hello";
if(std::binary_search(this->words.begin(), this->words.end(), aprox_key, smart_comp)){
std::cout << "Found" << std::endl;
}
}
I am trying to write my own compare function for comparing strings in binarysearch
I am getting following error:
xyz.cpp:40:85: error: no matching function for call to ‘binary_search(std::vector<std::basic_string<char> >::iterator, std::vector<std::basic_string<char> >::iterator, std::string&, <unresolved overloaded function type>)’
xyz.cpp:40:85: note: candidates are:
/usr/include/c++/4.6/bits/stl_algo.h:2665:5: note: template<class _FIter, class _Tp> bool std::binary_search(_FIter, _FIter, const _Tp&)
/usr/include/c++/4.6/bits/stl_algo.h:2698:5: note: bool std::binary_search(_FIter, _FIter, const _Tp&, _Compare) [with _FIter = __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >, _Tp = std::basic_string<char>, _Compare = bool (Spellcheck::*)(std::basic_string<char>, std::basic_string<char>)]
/usr/include/c++/4.6/bits/stl_algo.h:2698:5: note: no known conversion for argument 4 from ‘<unresolved overloaded function type>’ to ‘bool (Spellcheck::*)(std::basic_string<char>, std::basic_string<char>)’
Any help is appreciated...
Is there any problem with this code?
bool Spellcheck::smart_comp(string const value, string const key){
return true;
}
Other than it always returns true? Yes, the basic problem is that a member function has an implicit parameter this, so the signature does not match that of the expected predicate. You should be doing this function static or even a free function (friended if needed). Also you are copying the strings each time, it would be best if you take the arguments by const reference to avoid unneeded copies.
In case the real result of the predicate depends on the state of the Spellcheck object, you will have to bind that state to the member function in order to create a function object with the appropiate signature:
std::binary_search(
this->words.begin(), this->words.end()
, std::bind( &Spellcheck::smart_comp, this )
);
You're trying to pass a non-static member function, which is not convertible to the required binary function (on account of having three actual parameters).
Try declaring your smart_comp function static. (Of course then you can't refer to instance members; if you need statefulness, you'll have to write a full functor.)
Assuming this->words's type is std::vector<std::string> and func is a member of Spellcheck, you can work it around declaring smart_comp to be static. But I would think twice on your class design.

Using Qt: Invalid conversion from const void* to void* while using QList<Type *const>

I've been messing around with Qt and C++ for a while, but I've run into this error and can't seem to figure out why it crops up. There are a lot of other questions that have been answered out there with the const void* conversion error message, but I can't really see how the explanations help in my case, so here goes:
I have a reimplementation 'MyTypeManager' of QList< MyType *const>, so a list of const pointers to non-const MyTypes. However, when a function in my reimplementation, addMyType is called
void MyTypeManager::addMyType(MyType *const var)
{
this->append(var);
}
the following error(s) occur:
In file included from /usr/include/qt4/QtCore/QList:1:0,
from ../qtsdlthread/mytypemanager.h:4,
from ../qtsdlthread/mytypemanager.cpp:1:
/usr/include/qt4/QtCore/qlist.h: In member function ‘void QList<T>::node_construct(QList<T>::Node*, const T&) [with T = MyType* const]’:
/usr/include/qt4/QtCore/qlist.h:499:13: instantiated from ‘void QList<T>::append(const T&) [with T = MyType* const]’
../qtsdlthread/mytypemanager.cpp:20:26: instantiated from here
/usr/include/qt4/QtCore/qlist.h:359:58: error: invalid conversion from ‘const void*’ to ‘void*’
/usr/include/qt4/QtCore/qlist.h: In member function ‘void QList<T>::node_copy(QList<T>::Node*, QList<T>::Node*, QList<T>::Node*) [with T = MyType* const]’:
/usr/include/qt4/QtCore/qlist.h:666:9: instantiated from ‘QList<T>::Node* QList<T>::detach_helper_grow(int, int) [with T = MyType* const]’
/usr/include/qt4/QtCore/qlist.h:497:48: instantiated from ‘void QList<T>::append(const T&) [with T = MyType* const]’
../qtsdlthread/mytypemanager.cpp:20:26: instantiated from here
/usr/include/qt4/QtCore/qlist.h:386:17: error: invalid conversion from ‘const void*’ to ‘void*’
20:26 in mytypemanager is the this->append line posted above.
From the documentation:
QList's value type must be an assignable data type.
Alas MyType *const is not assignable. You have several remedies:
1. Make T a mutable pointer
2. Make T a pointer to your const pointer:
typedef MyType *const Element
void MyTypeManager::addMyType(Element var)
{
Element* ptr2ptr = new Element(var);
this->append(ptr2ptr);
}
But now you have 2 levels of memory management to worry about.
3. (Dangerous) Make T=MyType* and const-cast MyType *const into MyType *:
this->append(const_cast<MyType *>(var));
This will only work if you are certain var was originally created as a MyType* variable.

What does this mean: warning: converting from ‘void (ClassName::*)()’ to ‘void (*)()’

I have a member function in a class that has a callback, but the callback isn't strictly neccessary, so it has a default callback, which is empty. It seems to work fine, but I get an annoying warning:
warning: converting from ‘void (ClassName::*)()’ to ‘void (*)()’
I'm trying to figure out what it means and how to turn it off (or fix it if I really am doing something wrong). Here's some simple code:
class ClassName{
public:
void doSomething(void (*callbackFunction)() = (void(*)()) &ClassName::doNothing){
callbackFunction();
}
void doNothing(){}
};
int main(){
ClassName x;
x.doSomething();
return 0;
}
Note: If I do this (without explicitly casting it as a void(*)()):
void doSomething(void (*callbackFunction)() = &ClassName::doNothing)
I get this:
main.cpp:3: error: default argument for parameter of type ‘void (*)()’ has type ‘void (ClassName::*)()’
The issue is that you're passing a pointer to an instance method rather than a static method. If you make doNothing a static method (which means no implicit instance argument), the warning goes away.
Specifically,
warning: converting from ‘void (ClassName::*)()’ to ‘void (*)()’
exactly is saying that it's converting from a member function of class ClassName, to a non-member function.
See also the C++ FAQ Lite entry about pointers to member functions and pointers to functions.
Free function pointer is not the same as class member function pointer, which requires an instance of the class at call site. Though a static member function will do.

tr1::mem_fn and members with default arguments

I have class with a member function that takes a default argument.
struct Class
{
void member(int n = 0)
{}
};
By means of std::tr1::mem_fn I can invoke it:
Class object;
std::tr1::mem_fn(&Class::member)(object,10);
That said, if I want to invoke the callable member on the object with the default argument, what's the correct syntax?
std::tr1::mem_fn(&Class::member)(object); // This does not work
g++ complains with the following error:
test.cc:17: error: no match for call to ‘(std::tr1::_Mem_fn<void (Class::*)(int)>) (Class&)’
/usr/include/c++/4.3/tr1_impl/functional:551: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]
/usr/include/c++/4.3/tr1_impl/functional:556: note: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]
Still, the I have the same problem when Class::member is overloaded by members that takes different arguments...
Default functions are bound at call time, but can't be bound into any sort of wrapper implicitly, because of the way they are implemented. When you pass &Class::member, mem_fn only sees a void (Class::*)(int), and can't see the default argument. Using tr1::bind, you can bind the default argument explictly: std::tr1::bind(&Class::member, 0) or you can use it as you would mem_fn, but you can't do both in one object. You would have to write your own wrapper class for that.
As for overloads, you will have to explicitly specify the template arguments for mem_fn so the right function pointer is picked as in mem_fn<void(int)>(&Class::member).
The reason is that any default arguments do not change the function type of a function.
mem_fn has no way to know the function only requires 1 argument, or that the functions' second argument is optional, since all the knowledge it gets is given to it by the type of &Class::member (which stays void(Class::*)(int)) . It therefor requires an integer as the second argument.
If you want to pass the address of a member function overloaded, you have to cast to the right member function pointer type:
static_cast<void(Class::*)()>(&Class::member) instead of just &Class::member, so the compiler has a context to figure out which address is to be taken.
Edit: coppro has a nicer solution how to provide context: std::tr1::mem_fn<void()>(&Class::member)