Implement an interface with an anonymous class in C ++

In java, we can implement an interface with an anonymous class as follows:

 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 this in c ++? I wrote the following code, but I get a compilation 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 the "testIf" function template matches the argument list. Argument types: ( std::string , class <unnamed> )

what's wrong here? are there any other ways to do this?

Thanks!

+6
source share
4 answers

what's wrong here?

For polymorphism to work, you need to pass the base class by reference (or a pointer, if you want):

 bool testIf(T t, Predicate<T> & predicate) ^ 

With that in mind, the code works for me, although for my taste it smells a bit like Java.

Are there any other ways to do this?

In C ++ 11 or later, lambda would be more efficient, both in terms of performance and code noise. This eliminates the need to define and inherit from the 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 with a function object. It was a bit more verbose, but still gave a shorter, more efficient code than the inheritance approach.)

+9
source

C ++ only supports polymorphism in links 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 Predicate subclasses to this function.

+3
source

You can use one pointer for a 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; } 
+3
source

For this (polymorphism) to work, you need 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 ignore the possibility of polymorphism when references are used. On the other hand, it has a disatvantage that you should check for nullptr, and the syntax is not as good as before.

A more common way to implement this may be to use lambdas, for example:

 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; } 
+3
source

Source: https://habr.com/ru/post/982933/


All Articles