Reputation: 1886
i have a problem with this class.
the goal is to make the main function work properly. we were supposed to implement the "And" function object so that the code will work. i can't find what is the problem with our solution.
(the solution start and end are marked in comments in the code before the "main" function)
can you please help?
thanks
#include <iostream>
#include <algorithm>
using namespace std;
class NotNull
{
public:
bool operator()(const char* str) {return str != NULL;}
};
class BeginsWith
{
char c;
public:
BeginsWith(char c) : c(c) {}
bool operator()(const char* str) {return str[0] == c;}
};
class DividesBy {
int mod;
public:
DividesBy(int mod) : mod(mod) {}
bool operator()(int n) {return n%mod == 0;}
};
//***** This is where my sulotion starts ******
template <typename Function1, typename Function2, typename T>
class AndFunction
{
Function1 f1;
Function2 f2;
public:
AndFunction(Function1 g1, Function2 g2) : f1(g1), f2(g2) {}
bool operator()(T t)
{
return (f1(t) && f2(t));
}
};
template <typename Function1, typename Function2, typename T>
AndFunction <Function1, Function2, T>
bool And(Function1 f1, Function2 f2)
{
return AndFunction<Function1, Function2, T>(f1, f2);
}
//***** This is where my sulotion ends ******
int main(int argc, char** argv)
{
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
char* strings[4] = {"aba", NULL, "air", "boom"};
cout << count_if(array,array+10,And(DividesBy(2),DividesBy(4))) << endl;
// prints 2, since 4 and 8 are the only numbers which can be divided by
// both 2 and 4.
cout << count_if(strings,strings+4,And(NotNull(),BeginsWith('a'))) <<endl;
// prints 2, since only "aba" and "air" are both not NULL and begin
// with the character 'a'.
return 0;
}
Upvotes: 3
Views: 394
Reputation: 35980
Technically speaking you should be using the unary_function
and binary_function
classes as parents if you'd like them to place nice with STL algorithms. Here:
template<typename Func1, typename Func2,typename T>
struct AndFunction : public unary_function<T,bool>{
AndFunction(Func1 _func1, Func2 _func2)
: _myFunc1(_func1),
_myFunc2(_func2){}
bool operator()(T _t){
return _myFunc1(_t) && _myFunc2(_2);
}
private:
Func1 _myFunc1;
Func2 _myFunc2;
};
In your case you need to do
template<typename Func1, typename Func2, typename T>
AndFunction<Func1, Func2, T> And(Func1 _func1, Func2 _func2){
return AndFunction<Func1,Func2,T>(_func1,_func2);
};
so that you don't confuse the operator with object creation and that you specify how you are to receive the function instructions.
On the flip side, the way your main
works I think you really just want
struct And : public binary_function<bool, bool, bool>{
bool operator()(bool _1, bool _2){
return _1 && _2;
}
};
Hope that helps.
Upvotes: 1
Reputation: 26171
your not calling your overloaded ()
operator when you create the object here:
return AndFunction<Function1, Function2, T>(f1, f2);
(you need a ()
before the ;
) this code shouldn't even compile, actually, as currently it returns an object, not a bool.
EDIT: As pointed out, the function (bool And(Function1 f1, Function2 f2)
) must not return bool
but rather a functional object for count_if
to call via the overloaded ()
operator
Upvotes: 2
Reputation: 49812
The template parameter T
can't be inferred, it must be specified explicitly:
template <typename T, typename Function1, typename Function2>
AndFunction <Function1, Function2, T>
And(Function1 f1, Function2 f2)
{
return AndFunction<Function1, Function2, T>(f1, f2);
}
//***** This is where my sulotion ends ******
int main(int argc, char** argv)
{
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
char* strings[4] = {"aba", NULL, "air", "boom"};
cout << count_if(array,array+10,And<int>(DividesBy(2),DividesBy(4))) << endl;
// prints 2, since 4 and 8 are the only numbers which can be divided by
// both 2 and 4.
cout << count_if(strings,strings+4,And<const char*>(NotNull(),BeginsWith('a'))) <<endl;
// prints 2, since only "aba" and "air" are both not NULL and begin
// with the character 'a'.
return 0;
}
jpalecek's solution is better and works as follows:
//***** This is where my sulotion starts ******
template <typename Function1, typename Function2>
class AndFunction
{
Function1 f1;
Function2 f2;
public:
AndFunction(Function1 g1, Function2 g2) : f1(g1), f2(g2) {}
template<typename T> bool operator()(T)
{
return (f1(t) && f2(t));
}
};
template <typename Function1, typename Function2>
AndFunction <Function1, Function2>
And(Function1 f1, Function2 f2)
{
return AndFunction<Function1, Function2>(f1, f2);
}
//***** This is where my sulotion ends ******
Upvotes: 0
Reputation: 47762
Obviously, you don't know the T
parameter when creating your functor. Did you consider delaying the introduction of T
to the actual call (ie. making operator()
a member-template)?
Upvotes: 3