In java we can implement an interface
with Anonymous class like this :
import java.util.function.Predicate;
public class Test {
public static void main(String[] args) {
System.out.println(testIf("", new Predicate<String>() {
@Override
public boolean test(String s) {
return s.isEmpty();
}
}));
}
public static <T> boolean testIf(T t, Predicate<T> predicate) {
return predicate.test(t);
}
}
since Java 8 :
System.out.println(testIf("", String::isEmpty));
how can we do it in c++? I wrote the following code but I'm getting compile error :
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Predicate
{
public:
virtual bool test(T) = 0;
};
template <class T>
bool testIf(T t, Predicate<T> predicate)
{
return predicate.test(t);
}
int main()
{
class : public Predicate <string> {
public:
virtual bool test(string s)
{
return s.length() == 0;
}
} p;
string s = "";
cout << testIf(s, p);
cin.get();
return 0;
}
Error : no instance of function template "testIf" matches the argument list
argument types are: (std::string
, class <unnamed>
)
what's wrong here? are there other ways to do it?
Thanks!
what's wrong here?
For polymorphism to work, you need to pass the base class by reference (or pointer, if you prefer):
bool testIf(T t, Predicate<T> & predicate)
^
With that fixed, the code works for me, although it smells rather too much of Java for my taste.
are there other ways to do it?
In C++11 or later, a lambda would be more efficient, both in terms of performance, and noisiness of code. It removes the need to define and inherit from a base class, and to call a virtual function.
template <class T, class Predicate>
bool testIf(T t, Predicate predicate)
{
return predicate(t);
}
testIf(s, [](string const & s){return s.length() == 0;});
(Before C++11, you could do the same thing with a function object. It was slightly more verbose, but still gave shorter, more efficient code than the inheritance approach.)
C++ only supports polymorphism on reference and pointer types. Change your method to
template <class T>
bool testIf(T t, Predicate<T> & predicate)
{
return predicate.test(t);
}
then you can also pass subclasses of Predicate
to this function.
You can use one pointer for function:
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
template <class T>
class Predicate
{
public:
bool (*test)(T);
};
template <class T>
bool testIf(T t, Predicate<T> predicate)
{
return predicate.test(t);
}
bool one_test(string e)
{
return e.length() == 0;
}
int main()
{
Predicate<string> p;
p.test = one_test;
string s = "";
cout << testIf(s, p);
cin.get();
return 0;
}
In order for this (polymorphism) to work, you have to pass the predicate by pointer or by reference to testIF:
template <class T>
bool testIf(T t, Predicate<T>* predicate)
{
if (predicate == nullptr) return true;
return predicate->test(t);
}
int main()
{
class : public Predicate <string> {
public:
virtual bool test(string s)
{
return s.length() == 0;
}
} p;
string s = "";
cout << testIf(s, &p);
cin.get();
return 0;
}
I usually prefer to use pointers, because I tend to overlook the posibility of polymorphism, when references are used. On the other hand, it has the disatvantage, that you have to check for nullptr and the syntax is not as nice as before.
A more common way to implement this would be the use of lambdas E.g.:
template <class T,class Pred>
bool testIf2(T t, Pred predicate)
{
return predicate(t);
}
int main()
{
auto pred = [](const string& s){return s.length() == 0; };
string s = "";
cout << testIf2(s, pred );
cin.get();
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With