Написание класса Predicate на C++

Пытался написать аналог класса Predicate в Java на C++. В итоге вышло какое-то убожество:

template <typename T>
class Predicate {

private:

    Predicate<T> *other;

public:

    virtual bool test(T &t) = 0;

    Predicate<T> AND(Predicate<T> other);

    Predicate<T> OR(Predicate<T> other);

    Predicate<T> negate();
};

template<typename T>
Predicate<T> Predicate<T>::AND(Predicate<T> other) {
    Predicate<T> *t = this;
    class TmpPredicate : Predicate {

        TmpPredicate() {
            this->other = other;
        }

        bool test(T &t) {
            return t->test(t) && other.test(t);
        }
    };
    return TmpPredicate();
}

Остальные функции пока не реализовал.

В общем, это всё очень убого, но я понятия не имею, как это сделать нормально. Можете подсказать?

По задумке этот класс должен функционировать, как Predicate в Java. В идеальном варианте для работы с ним не нужно выделять динамическую память, работа с динамической памятью должна быть реализована в Predicate в его внутренней реализации.

Пример:

int main() {
    Predicate<char> p([](char c) { return c == 'A'; });
    Predicate<char> p2([](char c) { return c == 'B'; });
    cout << p('b') << '\n'; // 0
    cout << p.NOT()('a') << '\n'; // 1
    cout << p.AND(p2)('A') << '\n'; // 0
    cout << p.OR(p2)('B') << '\n'; // 1
    cout << p.OR(p2).OR(p)('A') << '\n'; // 1
    cout << p.OR(p2).OR(p).OR(p2)('a') << '\n'; // 0
}

Ответы (1 шт):

Автор решения: Имя Фамилия

Кто там говорил, что писать свой Predicate на C++ не целесообразно?
По мне так получилось очень целесообразно.

#include <memory>

template <typename T>
class Predicate {

    using Tester = bool(*)(const T&);

    enum Action {
        Test,
        And,
        Or,
        Not
    };

    class Data {

    public:

        Action action;
        Predicate *first{}, *second{};
        Tester tester{};

        explicit Data(const Action &action) : action(action) {

        }

        ~Data() {
            delete first;
            delete second;
        }
    };

    shared_ptr<Data> data;

    explicit Predicate(const Action &action) {
        data = make_shared<Data>(action);
    }

    Predicate(const Predicate &p) : data(p.data) {

    }

    Predicate(const Predicate &p1, const Predicate &p2, const Action &action) : Predicate(action) {
        data->first = new Predicate(p1);
        data->second = new Predicate(p2);
    }

public:

    explicit Predicate(const Tester &tester) : Predicate(Test) {
        data->tester = tester;
    }

    bool test(const T &t) const {
        switch (data->action) {
            case Test:
                return data->tester(t);
            case And:
                return (*data->first).test(t) && (*data->second).test(t);
            case Or:
                return (*data->first).test(t) || (*data->second).test(t);
            case Not:
                return !(*data->first).test(t);
        }
    }

    bool operator()(const T &t) const {
        return test(t);
    }

    Predicate AND(const Predicate &other) const {
        return Predicate(*this, other, And);
    }

    Predicate OR(const Predicate &other) const {
        return Predicate(*this, other, Or);
    }

    Predicate NOT() const {
        Predicate notThis(Not);
        notThis.data->first = new Predicate(*this);
        return notThis;
    }
};
→ Ссылка