using comparing function - c++

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.

Related

partial_sort and smart pointers

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));

call of an object of a class type without appropriate operator()

I have this following function to test out thrust but it doesn't compile. It appears my predicate is not valid and my knowledge of C/C++ is not strong enough to know what I need to do correct the compilation issue. Please could someone explain what's going on here and how I can fix it.
void filter(device_vector<int>& x,
device_vector<int>& y,
thrust::unary_function<int,bool> f) {
thrust::copy_if(x.begin(), x.end(), y.end(), f);
}
nvcc -o test test.cu -O2
/usr/lib/nvidia-cuda-toolkit/include/thrust/detail/internal_functional.h(102): error: call of an object of a class type without appropriate operator() or conversion functions to pointer-to-function type
detected during:
instantiation of "__nv_bool thrust::detail::predicate_to_integral<Predicate, IntegralType>::operator()(const T &) [with Predicate=thrust::unary_function<__nv_bool, int>, IntegralType=std::ptrdiff_t, T=int]"
/usr/lib/nvidia-cuda-toolkit/include/thrust/detail/function.h(187): here
instantiation of "Result thrust::detail::host_device_function<Function, Result>::operator()(const Argument &) const [with Function=thrust::detail::predicate_to_integral<thrust::unary_function<__nv_bool, int>, std::ptrdiff_t>, Result=std::ptrdiff_t, Argument=thrust::device_reference<int>]"
/usr/lib/nvidia-cuda-toolkit/include/thrust/iterator/transform_iterator.h(306): here
instantiation of "thrust::detail::transform_iterator_base<AdaptableUnaryFunction, Iterator, Reference, Value>::type::reference thrust::transform_iterator<AdaptableUnaryFunction, Iterator, Reference, Value>::dereference() const [with AdaptableUnaryFunction=thrust::detail::predicate_to_integral<thrust::unary_function<__nv_bool, int>, std::ptrdiff_t>, Iterator=thrust::detail::normal_iterator<thrust::device_ptr<int>>, Reference=std::ptrdiff_t, Value=thrust::use_default]"
/usr/lib/nvidia-cuda-toolkit/include/thrust/iterator/iterator_facade.h(128): here
instantiation of "Facade::reference thrust::iterator_core_access::dereference(const Facade &) [with Facade=thrust::transform_iterator<thrust::detail::predicate_to_integral<thrust::unary_function<__nv_bool, int>, std::ptrdiff_t>, thrust::detail::normal_iterator<thrust::device_ptr<int>>, std::ptrdiff_t, thrust::use_default>]"
/usr/lib/nvidia-cuda-toolkit/include/thrust/iterator/iterator_facade.h(305): here
Let's look at some reference first:
The function object pred shall not apply any non-constant function
through the dereferenced iterator. This function object may be a
pointer to function or an object of a type with an appropriate
function call operator.
From "Predicate".
Thus, you shouldn't limit the choices of the caller to unary_function. In a case like this, any object, function, whatever that can be used in the context of copy_if should be allowed to pass. Actually, in vanilla C++ unary_function is deprecated (in favor of std::function, which shouldn't be used here anyway for exactly the same reasons).

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.

C++ templates no matching function call

I have a member function of a template class declared as such:
template <class T>
int Data<T>::getPosition(vector<T> stuff, T newStuff, bool ascending)
I call this somewhere with the line
frequencies.insert(frequencies.begin() + getPosition(frequencies, current, ascending),
frequencies[i]);
The variables for that line are declared as:
vector<T> temp;
vector<int> frequencies;
int current = frequency.find(words[i])->second;
However, the call to getPosition gives this error:
Data.h|158|error: no matching function for call to 'primitives::Data<double>::getPosition(std::vector<int, std::allocator<int> >&, int&, bool&)'|
Data.h|165|note: candidates are: int primitives::Data<T>::getPosition(std::vector<T, std::allocator<_CharT> >, T, bool) [with T = double]|
What am I doing wrong here?
getPosition takes three arguments of type vector<T>, T and bool. The templated type T in this case is double (as is shown in the error message), and yet you are trying to pass vector<int> and int as the first and second argument, respectively.
Perhaps the parameters for getPosition should not be templated? Depends on what you are trying to achieve - you do have hard-coded int-vectors there, after all.
Your function prototype gets templated on Data<t>, and it looks like you're performing this call on an object with type Data<double> and passing a std::vector<int> and an int, when it probably expects a std::vector<double> and a double to correspond to the initial templated type of the Data object.
vector<T> temp;
Shouldn't T here be some type like int, double or bool?

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)