Good afternoon, please tell me how (and whether it is possible to do this at all) to write one function that performs similar actions (arithmetic, logical, etc.) on data of different types. If possible, it would also be nice to change the type of action (if the language allows it, of course). If you can, give a couple of examples.

    2 answers 2

    The classic example of comparing two variables with a predicate: Two predicates:

    template<class T> class CMPLess { public: bool operator() (T a, T b) { return a<b; } }; template<class T> class CMPEqual { public: bool operator() (T a, T b) { return a==b; } }; 

    Comparison function:

     template<class T, class CMP> bool equal_if(T a, T b, CMP cmp) { return cmp(a,b); } 


     int a=2, b=3; if (equal_if(a, b, CMPLess<int>())) { // a<b } else if (equal_if(a, b, CMPEqual<int>())) { // a==b } 

    In this example, not only the types are not defined, but also the action that is performed in the function equal_if , it is not known until these functions are called.

    UPD : Update to minimize type references. In the example above, it is passed to the parameter CMPEqual <int> () , it is asked why you specify the type explicitly if it can be implicitly deduced from the type of the variables a and b . Here's how to do it:

    Change the comparison function:

     template<template<class> class CMP, class T> bool equal_if(T a, T b) { return CMP<T>()(a,b); } 

    The call changes in such a way that types are explicitly specified only when creating variables:

     int a=2, b=3; if (equal_if<CMPLess>(a, b)) { // a<b } 
    • Sorry to ask the question in the comments, I just can not formulate it properly without the material given in this answer. Is it possible not to prescribe a type when using a template (in this case <int>) explicitly when writing code, i.e. Can it dynamically change? If not, what is the difference from macros? - avp
    • @avp for specifying the type when using the template, see the update response. Of course, the type cannot change dynamically (that is, during the execution of the program). Because instantiation (generation) of a template occurs at compilation. It differs from macros in many ways, for example, by strict typing, support for overloading and much more than that (read the literature - there is a lot about this already written and rewritten). - IAZ
    • Thank. Do not you think that all such things (as well as complex macros) "obscure" the program? Especially when you need to edit someone else's code. - avp
    • @avp, on the contrary, OOP, especially when performed in C ++, makes the program slim, and the resulting code can be very simple. Like Matrix a, b; a + = b; As a result, we get code that can be reused, and a programmer who does not know algebra and even what a matrix is ​​or, as in the comparison example, a programmer using equal_if does not have to know how templates are written, he only needs an example of calling it. - IAZ
    • @JAZ! I'm not going to polemize, rather, just complaining. We all make mistakes and, unfortunately, people write insides too. Add a chronic lack of documentation and it will become clear that to catch a nontrivial error in this code m. harder than gogett spegty. - avp 1:01 pm

    There are two options.

    1) overloading functions. This means that we do N functions with the same name, but different types of input data. But you need to be careful. Those. So you can do it, but it's too little:

     char add(char,char); int add(int,int); double add(double,double); //... где-то в коде int x=10, y=0; std::cout<<x<<"+"<<y<<add((double)x,y); // так какой же вариант ф-ции выбрать!? // а так работает: std::cout<<x<<"+"<<y<<add((double)x,(double)y); 

    2) use of templates. Templates are very entertaining. In fact, the pattern unfolds into the real code at the place of its use in the code. Therefore, the code swells, but flexibility is provided.