読者です 読者をやめる 読者になる 読者になる

lambda作ってみた(Not Boost)

前回の簡易ラムダを元にしてlambdaを作ってみました


現時点では、簡単な計算しかできません
(&&とか||で繋ぐこともできないし、%も使えない)


そのうちいろいろ修正するかも(しないかも)



サンプル(できること全部)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <shand/lambda.hpp>

using namespace std;
using namespace shand;

struct person {
    int age;
    string name;

    person(int age, const string& name)
        : age(age), name(name) {}
};

int main()
{
    {
        vector<int> v;
        v.push_back(3);
        v.push_back(1);
        v.push_back(4);

        find_if(v.begin(), v.end(), lambda() < 2);
        find_if(v.begin(), v.end(), lambda() > 2);
        find_if(v.begin(), v.end(), lambda() <= 3);
        find_if(v.begin(), v.end(), lambda() >= 2);
        find_if(v.begin(), v.end(), lambda() == 3);
        find_if(v.begin(), v.end(), lambda() != 2);

        for_each(v.begin(), v.end(), lambda() = 2);
        for_each(v.begin(), v.end(), lambda() += 2);
        for_each(v.begin(), v.end(), lambda() -= 2);
        for_each(v.begin(), v.end(), lambda() *= 2);
        for_each(v.begin(), v.end(), lambda() /= 2);

        for_each(v.begin(), v.end(), cout << lambda());
    }

    {
        vector<person> v;
        v.push_back(person(23, "Akira"));
        v.push_back(person(38, "Johnny"));
        v.push_back(person(16, "Millia"));

        find_if(v.begin(), v.end(), lambda(&person::age) < 20);
        find_if(v.begin(), v.end(), lambda(&person::age) > 20);
        find_if(v.begin(), v.end(), lambda(&person::age) <= 23);
        find_if(v.begin(), v.end(), lambda(&person::age) >= 20);
        find_if(v.begin(), v.end(), lambda(&person::age) == 38);
        find_if(v.begin(), v.end(), lambda(&person::age) != 20);

        for_each(v.begin(), v.end(), lambda(&person::age) = 20);
        for_each(v.begin(), v.end(), lambda(&person::age) += 20);
        for_each(v.begin(), v.end(), lambda(&person::age) -= 20);
        for_each(v.begin(), v.end(), lambda(&person::age) *= 20);
        for_each(v.begin(), v.end(), lambda(&person::age) /= 20);

        for_each(v.begin(), v.end(), cout << lambda(&person::name));
    }

    return 0;
}

ソース(shand/lambda.hpp)

#ifndef SHAND_LAMBDA_INCLUDE
#define SHAND_LAMBDA_INCLUDE

#include <ostream>
#include <functional>

namespace shand {
namespace lambda_detail {
    #define CREATE_MEMBER_COMP_FUNCTOR(Class, Operator)                 \
    template <class ClassName, class T, class U>                        \
    class Class : public std::binary_function<ClassName, U, bool> {     \
        T ClassName::* member_;                                         \
    public:                                                             \
        explicit Class(T ClassName::* member)                           \
            : member_(member) {}                                        \
                                                                        \
        bool operator()(const ClassName &lhs, const U &rhs) const       \
        {                                                               \
            return lhs.*member_ Operator rhs;                           \
        }                                                               \
    };

    CREATE_MEMBER_COMP_FUNCTOR(mem_less_functor,            <);
    CREATE_MEMBER_COMP_FUNCTOR(mem_greater_functor,         >);
    CREATE_MEMBER_COMP_FUNCTOR(mem_less_equal_functor,      <=);
    CREATE_MEMBER_COMP_FUNCTOR(mem_greater_equal_functor,   >=);
    CREATE_MEMBER_COMP_FUNCTOR(mem_equal_functor,           ==);
    CREATE_MEMBER_COMP_FUNCTOR(mem_not_equal_functor,       !=);

    #define CREATE_UNARY_FUNCTOR(Class, Operator) \
    template <class T>                      \
    class Class {                           \
        T value_;                           \
    public:                                 \
        explicit Class(const T& value)      \
            : value_(value) {}              \
                                            \
        template <class U>                  \
        void operator()(U& value) const     \
        {                                   \
            value Operator value_;          \
        }                                   \
    };

    CREATE_UNARY_FUNCTOR(assign,            =);
    CREATE_UNARY_FUNCTOR(plus_equal,        +=);
    CREATE_UNARY_FUNCTOR(minus_equal,       -=);
    CREATE_UNARY_FUNCTOR(multiply_equal,    *=);
    CREATE_UNARY_FUNCTOR(divide_equal,      /=);


    #define CREATE_MEM_UNARY_FUNCTOR(Class, Operator) \
    template <class ClassName, class T, class U>                    \
    class Class {                                                   \
        T ClassName::* member_;                                     \
        U value_;                                                   \
    public:                                                         \
        explicit Class(T ClassName::* member, const U& value)       \
            : member_(member), value_(value) {}                     \
                                                                    \
        void operator()(ClassName& obj)                             \
        {                                                           \
            obj.*member_ Operator value_;                           \
        }                                                           \
    };

    CREATE_MEM_UNARY_FUNCTOR(mem_assign,            =);
    CREATE_MEM_UNARY_FUNCTOR(mem_plus_equal,        +=);
    CREATE_MEM_UNARY_FUNCTOR(mem_minus_equal,       -=);
    CREATE_MEM_UNARY_FUNCTOR(mem_multiply_equal,    *=);
    CREATE_MEM_UNARY_FUNCTOR(mem_divide_equal,      /=);

    class lambda_stream {
        std::ostream& os_;
    public:
        lambda_stream(std::ostream& os)
            : os_(os) {}

        template <class T>
        void operator()(const T& value)
        {
            os_ << value;
        }
    };

    template <class ClassName, class T>
    class mem_lambda_stream {
        std::ostream& os_;
        T ClassName::* member_;
    public:
        mem_lambda_stream(T ClassName::* member, std::ostream& os)
            : member_(member), os_(os) {}

        void operator()(const ClassName& value)
        {
            os_ << value.*member_;
        }
    };
} // namespace shand::lambda_detail


struct lambda_t {
    template <class T>
    friend std::binder2nd<std::less<T> > operator<(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::less<T>(), value);
    }

    template <class T>
    friend std::binder2nd<std::greater<T> > operator>(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::greater<T>(), value);
    }

    template <class T>
    friend std::binder2nd<std::less_equal<T> > operator<=(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::less_equal<T>(), value);
    }

    template <class T>
    friend std::binder2nd<std::greater_equal<T> > operator>=(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::greater_equal<T>(), value);
    }

    template <class T>
    friend std::binder2nd<std::equal_to<T> > operator==(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::equal_to<T>(), value);
    }

    template <class T>
    friend std::binder2nd<std::not_equal_to<T> > operator!=(const lambda_t&, const T& value)
    {
        return std::bind2nd(std::not_equal_to<T>(), value);
    }

    template <class T>
    lambda_detail::assign<T> operator=(const T& value)
    {
        return lambda_detail::assign<T>(value);
    }

    template <class T>
    lambda_detail::plus_equal<T> operator+=(const T& value)
    {
        return lambda_detail::plus_equal<T>(value);
    }

    template <class T>
    lambda_detail::minus_equal<T> operator-=(const T& value)
    {
        return lambda_detail::minus_equal<T>(value);
    }

    template <class T>
    lambda_detail::multiply_equal<T> operator*=(const T& value)
    {
        return lambda_detail::multiply_equal<T>(value);
    }

    template <class T>
    lambda_detail::divide_equal<T> operator/=(const T& value)
    {
        return lambda_detail::divide_equal<T>(value);
    }
};

template <class ClassName, class T>
class mem_lambda_t {
    T ClassName::* member_;
public:
    explicit mem_lambda_t(T ClassName::* member)
        : member_(member) {}

    template <class U>
    friend std::binder2nd<lambda_detail::mem_less_functor<ClassName, T, U> >
        operator<(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_less_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    friend std::binder2nd<lambda_detail::mem_greater_functor<ClassName, T, U> >
        operator>(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_greater_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    friend std::binder2nd<lambda_detail::mem_less_equal_functor<ClassName, T, U> >
        operator<=(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_less_equal_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    friend std::binder2nd<lambda_detail::mem_greater_equal_functor<ClassName, T, U> >
        operator>=(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_greater_equal_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    friend std::binder2nd<lambda_detail::mem_equal_functor<ClassName, T, U> >
        operator==(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_equal_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    friend std::binder2nd<lambda_detail::mem_not_equal_functor<ClassName, T, U> >
        operator!=(const mem_lambda_t& func, const U& value)
    {
        return std::bind2nd(lambda_detail::mem_not_equal_functor<ClassName, T, U>(func.member_), value);
    }

    template <class U>
    lambda_detail::mem_assign<ClassName, T, U> operator=(const U& value)
    {
        return lambda_detail::mem_assign<ClassName, T, U>(member_, value);
    }

    template <class U>
    lambda_detail::mem_plus_equal<ClassName, T, U> operator+=(const U& value)
    {
        return lambda_detail::mem_plus_equal<ClassName, T, U>(member_, value);
    }

    template <class U>
    lambda_detail::mem_minus_equal<ClassName, T, U> operator-=(const U& value)
    {
        return lambda_detail::mem_minus_equal<ClassName, T, U>(member_, value);
    }

    template <class U>
    lambda_detail::mem_multiply_equal<ClassName, T, U> operator*=(const U& value)
    {
        return lambda_detail::mem_multiply_equal<ClassName, T, U>(member_, value);
    }

    template <class U>
    lambda_detail::mem_divide_equal<ClassName, T, U> operator/=(const U& value)
    {
        return lambda_detail::mem_divide_equal<ClassName, T, U>(member_, value);
    }

    template <class ClassNameU, class U>
    friend lambda_detail::mem_lambda_stream<ClassNameU, U>
    operator<<(std::ostream& os, const mem_lambda_t<ClassNameU, U>& ml);
};

inline lambda_detail::lambda_stream operator<<(std::ostream& os, const lambda_t&)
{
    return lambda_detail::lambda_stream(os);
}

template <class ClassName, class T>
inline lambda_detail::mem_lambda_stream<ClassName, T>
    operator<<(std::ostream& os, const mem_lambda_t<ClassName, T>& ml)
{
    return lambda_detail::mem_lambda_stream<ClassName, T>(ml.member_, os);
}


inline lambda_t lambda()
{
    return lambda_t();
}

template <class ClassName, class T>
inline mem_lambda_t<ClassName, T> lambda(T ClassName::* member)
{
    return mem_lambda_t<ClassName, T>(member);
}

} // namespace shand

#endif // SHAND_LAMBDA_INCLUDE

ライブラリまとめ