#include <iostream>

bool condEq5 ( int x ) {
    return x==5;
}

bool condRange100 ( int x ) {
    return (x>=0) && (x<=100);
}

int* find2 ( int* pool, int n, bool (*c)(int) ) {
    int* p = pool;
    for ( int i = 0; i<n; i++ ) {
        if ( c(*p) ) return p;
        p++;
    }
    return nullptr;
}
/*
// functional type
class GreaterThan5 {
public:
    bool operator()(int x) { return x>5; }
};

int* find2 ( int* pool, int n, GreaterThan5 c ) {
    int* p = pool;
    for ( int i = 0; i<n; i++ ) {
        if ( c(*p) ) return p;   // c.operator()(*p)
        p++;
    }
    return nullptr;
}
*/
/*
template < typename T, typename Comparator >
T* find2 ( T* pool, int n, Comparator c ) {
    T* p = pool;
    for ( int i = 0; i<n; i++ ) {
        if ( c(*p) ) return p;
        p++;
    }
    return 0;
}

// different comparators
template < typename T, T N >
class Greater {
public:
    bool operator()(T x) { return x>N; }
};
*/

int main() {
    int arr[] = {1, 3, 5, 7, 9};
    int* p = find2(arr,5, condEq5);
    //int* p = find2(arr,5, [](int x) -> bool {return x==5;});   // lambda expression
    std::cout << p << " " << *p << " : an array element is at index: " << p - arr << std::endl;
    p = find2(arr,5,condRange100);
    std::cout << p << " " << *p << " : an array element is at index: " << p - arr << std::endl;
/*
    bool (*pf)(int) = condEq5;   // pointer to function
    std::cout << condEq5(2) << std::endl;  // explicit function call
    std::cout << pf(2) << std::endl;         // implicit function call
    pf = condRange100;
    p = find2(arr,5,pf);
    std::cout << p << " " << *p << " : an array element is at index: " << p - arr << std::endl;
*/
/*
    std::cout << "-------------------" << std::endl;
    GreaterThan5 c; // c is functional object
    p = find2(arr,5, c);
    std::cout << p << " " << *p << " : an array element is at index: " << p - arr << std::endl;

    std::cout << "-------------------" << std::endl;
    Greater<int,7> a;
     = find2(arr,5, a);
    //p = find2(arr,5, Greater<int,7>());  //calling defualt constructor
    std::cout << p << " " << *p << " : an array element is at index: " << p-arr << std::endl;
*/
    return 0;
}