I am looking at someone's code, I don't understand how the object getting initialized here:
template <typename String>
void test_numbers()
{
SampleClass<String> compare;
String lhs = "abc";
String rhs = "efg";
check_equality(compare(lhs, rhs), true);
}
The object compare is created of class type SampleClass and then assigned 2 strings when passed on as a parameter. How this initialization works? Any comments? suggestions?
//I am initialised with my default constructor (no args)
SampleClass<String> compare;
//I am initialised with my `const char*` constructor (and assignment operator)
String lhs = "abc";
String rhs = "efg";
//Compare (already initialised) is being invoked by it's `operator()`
check_equality(compare(lhs, rhs), true);
compare is already constructed. It has an operator() implemented that allows it to appear as a function, accepting arguments.
you can make your own easily.
struct op_test{
int i;
op_test(int i_) : i(i_){}
int operator()(int j)const { return j*i; }
};
:::
op_test ot(5);
ot(6); //5*6
The reason this is useful is because we can do thing like this.
std::vector<int> a(700); //700 ints
std::transform(a.begin(), a.end(), b.begin(), op_test(5));
//or
std::transform(a.begin(), a.end(), b.begin(), &my_func); //calls a function
std::transform(a.begin(), a.end(), b.begin(), [](int i){ return i*5; }); //lambda
see here:
http://msdn.microsoft.com/en-us/library/5tk49fh2(v=vs.80).aspx
useful with
http://en.cppreference.com/w/cpp/algorithm
It simply creates an automatic variable of type SampleClass<String>. Then its operator() is called with two String arguments.
Related
I'm trying to figure out a nice way to find the index of a certain object in a vector - by comparing a string to a member field in the object.
Like this:
find(vector.begin(), vector.end(), [object where obj.getName() == myString])
I have searched without success - maybe I don't fully understand what to look for.
You can use std::find_if with a suitable functor. In this example, a C++11 lambda is used:
std::vector<Type> v = ....;
std::string myString = ....;
auto it = find_if(v.begin(), v.end(), [&myString](const Type& obj) {return obj.getName() == myString;})
if (it != v.end())
{
// found element. it is an iterator to the first matching element.
// if you really need the index, you can also get it:
auto index = std::distance(v.begin(), it);
}
If you have no C++11 lambda support, a functor would work:
struct MatchString
{
MatchString(const std::string& s) : s_(s) {}
bool operator()(const Type& obj) const
{
return obj.getName() == s_;
}
private:
const std::string& s_;
};
Here, MatchString is a type whose instances are callable with a single Type object, and return a boolean. For example,
Type t("Foo"); // assume this means t.getName() is "Foo"
MatchString m("Foo");
bool b = m(t); // b is true
then you can pass an instance to std::find
std::vector<Type>::iterator it = find_if(v.begin(), v.end(), MatchString(myString));
In addition to the Lambda and the handwritten functor used by juancho, you have the possibility to use boost::bind (C++03) or std::bind (C++11) and a simple function:
bool isNameOfObj(const std::string& s, const Type& obj)
{ return obj.getName() == s; }
//...
std::vector<Type>::iterator it = find_if(v.begin(), v.end(),
boost::bind(&isNameOfObj, myString, boost::placeholders::_1));
Or, if Type has a method isName:
std::vector<Type>::iterator it = find_if(v.begin(), v.end(),
boost::bind(&Type::isName, boost::placeholders::_1, myString));
This is just for completeness. In C++11 I'd prefer Lambdas, in C++03 I'd use bind only if the comparison function itself exists already. If not, prefer the functor.
PS: Since C++11 has no polymorphic/templated lambdas, bind still has it's place in C++11, e.g. if the parameter types are unknown, hard to spell, or otherwise not easy to deduce.
A simple iterator may help.
typedef std::vector<MyDataType> MyDataTypeList;
// MyDataType findIt should have been defined and assigned
MyDataTypeList m_MyObjects;
//By this time, the push_back() calls should have happened
MyDataTypeList::iterator itr = m_MyObjects.begin();
while (itr != m_MyObjects.end())
{
if(m_MyObjects[*itr] == findIt) // any other comparator you may want to use
// do what ever you like
}
When I define the custom comparison function inside the class I'll get the error:
'Solution::myfunction': non-standard syntax; use '&' to create a pointer to member
But if I define it outside the class it works. How can I define it inside the class?
class Solution {
public:
bool myfunction(const vector<int> &i, const vector<int> &j) {
return i.front() < j.front());
}
vector<vector<int>> vec;
...
sort(vec.rbegin(), vec.rend(), myfunction);
}
Thanks
Non-static member functions take an implicit this as first parameter. The correct way to call your member function would be
Solution s;
std::vector<int> x;
s.myfunction(x,x);
when you actually want a function that only takes two vectors as parameter. Declare it as static or use a free-function (the prefered way).
PS: Unless you need to call the same comparison function in different scopes, I would suggest to use a lambda:
sort(vec.begin(), vec.end(),
[](const vector<int> &i, const vector<int> &j) {
return i.front()<j.front();
}
);
There are couple way to fix it:
I prefer provide lambda:
sort(vec.rbegin(), vec.rend(), [](const auto &a, const auto &b)
{
return std::lexicographical_compare(a.begin(), a.end(),
b.begin(), b.end());
});
Other way is to provide comparetion class:
class CmpIntVectors {
public:
bool operator(const vector<int> &a, const vector<int> &b) const
{
return std::lexicographical_compare(a.begin(), a.end(),
b.begin(), b.end());
}
};
...
sort(vec.rbegin(), vec.rend(), CmpIntVectors{});
Or make myfunction static.
Disclaimer: I'm assuming that your vec looks like this:
std::vector<std::vector<int>> vec;
Lambdas are the preferred way nowadays instead of defining your own comparison function. They are more readable and in-place, i.e. you can see the code where you call sort() rather than look in some header file elsewhere.
If for some reason you still want to use class member function, then use lambda and pass this to it:
sort(vec.rbegin(), vec.rend(), [this](const vector<int> &i, const vector<int> &j){
return this->myfunction(i, j);
});
With a number array nums, I'd like to sort the unique numbers by the frequency of their occurrences. The compiler is complaining about passing the unordered_map as 'this' argument discards qualifiers. How do I fix this?
void sortByFreq(const vector<int>& nums) {
unordered_map<int, int> counts;
for (auto i: nums) ++counts[i];
auto byCount = [counts](const int& a, const int& b) { return counts[a] > counts[b]; };
priority_queue<int, vector<int>, decltype(byCount)> minFreq(byCount);
for (auto& kv: counts) {
minFreq.push(kv.first);
}
......
}
Why you there is a priority_queue? Looks like we missing some information.
There are couple ways to fix issue with counts and lambda:
use at instead operator[] - IMO best solution
capture counts by reference
make lambda mutable (I don't like this one)
From what you have described this should do the job:
vector<int> sortedByFreq(const vector<int>& nums)
{
unordered_map<int, int> counts;
for (auto i : nums)
++counts[i];
vector<int> result = nums;
std::sort(result.begin(), result.end(),
[counts](auto a, auto b) {
return counts.at(a) > counts.at(b);
});
return result;
}
You need to make the lambda mutable, to allow the non-const member function to be called on the copy-captured counts. (Note that the operator[] of std::unordered_map is a non-const member function, which will perform insertion if the key does not exist.)
mutable: allows body to modify the parameters captured by copy, and to call their non-const member functions
e.g.
auto byCount = [counts](const int& a, const int& b) mutable { return counts[a] > counts[b]; };
You can use at instead of operator[], as it has a const qualified overload.
auto byCount = [counts](const int& a, const int& b) { return counts.at(a) > counts.at(b); };
I am trying to find an object in a vector of objects whos value of a member variable is true. Could it be done without defining a lamba function or function object, by just specifying the member variable itself:
class A
{
public:
explicit A(bool v, int v2, float v3) : value(v), value2(v2), value3(v3)
{}
...
bool value;
int value2;
float value2;
...
}
int main()
{
std::vector<A> v;
v.push_back(A(false, 1, 1.0));
v.push_back(A(true, 2, 2.0));
v.push_back(A(false, 3, 3.0));
auto iter = std::find_if(v.begin(), v.end(), &A::value);
}
Compiling as is above does not work as it assumes a A* and not A.
Not that its a problem to use lambdas, just curious.
You may use std::mem_fn
auto iter = std::find_if(v.begin(), v.end(), std::mem_fn(&A::value));
Demo
Note that range library should allow directly:
auto iter = range::find_if(v, &A::value);
If you cannot use C++11 lambdas, you can do that with std::bind:
auto iter = std::find_if(v.begin(), v.end(), std::bind(&A::value, std::placeholders::_1));
A solution could be the following
(Optional) Don't mark your constructor A(bool) as explicit to allow implicit conversion from bool to A (live demo on coliru)
Overload operator==() so that it only uses value to establish equality.
You can also supply an operator==(bool v) { return value == v;} (see this demo)
Of course I would advise you not to use that solution as it is quite dirty. Just supply a predicate using std::find_if to do the job. Note that the said predicate must have an operator() so of course you cannot supply a value such as a bool as the predicate to std::find_if
So I was trying to add to a class a function that compares two std::string's disregarding case from here: Case insensitive standard string comparison in C++.
#include <iostream>
#include <string>
using namespace std;
class foo {
public:
bool icompare_pred(char a, char b) {
return std::tolower(a) == std::tolower(b);
}
bool icompare( string a, string b){
return equal( a.begin(), a.end(), b.begin(), icompare_pred);
}
};
int main() {
}
The code doesn't compile, even more: it sends me into the depths of STL with an error
[Error] must use '.*' or '->*' to call pointer-to-member function in '__binary_pred (...)', e.g. '(... ->* __binary_pred) (...)'
in this part
stl_algobase.h
template<typename _IIter1, typename _IIter2, typename _BinaryPredicate>
inline bool
equal(_IIter1 __first1, _IIter1 __last1,
_IIter2 __first2, _BinaryPredicate __binary_pred)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_IIter1>)
__glibcxx_function_requires(_InputIteratorConcept<_IIter2>)
__glibcxx_requires_valid_range(__first1, __last1);
for (; __first1 != __last1; ++__first1, ++__first2)
if (!bool(__binary_pred(*__first1, *__first2)))
return false;
return true;
}
Well, what do I do? How do I fix this error?
You should use static function as predicate:
static bool icompare_pred(char a, char b) {
^^^^^^
or you can use lambda:
bool icompare( string a, string b){
return equal( a.begin(), a.end(), b.begin(),
[](char a, char b){return std::tolower(a) == std::tolower(b);});
}
Make icompare_pred() a static function of foo
static bool icompare_pred(char a, char b) {
// ^^^^^^
return std::tolower(a) == std::tolower(b);
}
or move the function out of the class foo as free function.
You would need your comparator to be static
static bool icompare_pred(char a, char b) {
return std::tolower(a) == std::tolower(b);
}
Also since icompare isn't static, you'd have to call it from a foo instance, like so
int main()
{
foo f;
std::cout << f.icompare("TEST", "test");
}
Live demo, output
1
There are multiple errors in your code, some of which are apparently not caught by your compiler (due to its permissiveness?). For example, icompare_pred by itself is not a valid C++ expression. Non-static member function names by themselves do not form valid expressions in C++. You have to either call the function using () operator or form a pointer to it using & operator and a qualified name. What you are trying to do would be properly expressed as
bool icompare( string a, string b){
return equal( a.begin(), a.end(), b.begin(), &foo::icompare_pred);
}
Both the & operator and the foo:: prefix are mandatory.
And this is where we run into the second error. A two-parameter non-static member function actually has three parameters: the two that you declared explicitly and an implicit this parameter. So, in your code you are passing a three-parameter function where a two-parameter one is required. This is one way to "interpret" this error.
In order to make your member function usable as a predicate for std::equal you can "bind" the implicit this parameter - attach a specific fixed value to it - thus converting a three-parameter function into a two-parameter one. For example
bool icompare( string a, string b){
return equal( a.begin(), a.end(), b.begin(),
std::bind(&foo::icompare_pred, this,
std::placeholders::_1, std::placeholders::_2));
}
This should compile and work as intended.
However, since your comparison predicate does not really need or care about that implicit this parameter, a better approach would be to get rid of it entirely: just declare your comparator as static, as suggested in other answers. If you do that, the &foo::icompare_pred syntax will become unnecessary as well and you'll be able to just use icompare_pred in its place as in your original code.