Zipper and other Function Objects

There are some useful function objects, which can be used with mappable.

Zippers and pairers pack things into tuples and pairs respectively:

struct zipper
{
    template<class... Args>
    auto operator()(Args&&... args)
    {
        return std::make_tuple(std::forward<Args>(args)...);
    }
};

struct pairer
{
    template<class L,class R>
    auto operator()(L&& l, R&& r)
    {
        return std::make_pair(std::forward<L>(l),std::forward<R>(r));
    }
};

If you need to pack constant values or references, you can use a variation on this concept. The pair variant is particularly useful for inserting values into std::map.

template<class... Args>
struct zipper_t
{
    template<class... Args_>
    auto operator()(Args_&&... args)
    {
        return std::tuple<Args...>(std::forward<Args_>(args)...);
    }
};

template<class L,class R>
struct pairer_t
{
    template<class L_,class R_>
    auto operator()(L_&& l, R_&& r)
    {
        return std::pair<L,R>(std::forward<L_>(l),std::forward<R_>(r));
    }
};

Following the nomenclature of std::make_pair and std::make_shared, make just makes an object. This is quite useful since you can’t get a pointer to a constructor.

template<class T>
struct make
{
    template<class... Args>
    auto operator()(Args&&... args)
    {
        return T(std::forward<Args...>(args...));
    }
};

Less type strict versions of std::plus and its siblings are useful for when you need to operate on different types, such as matrices and vertices.

#define FC_BINARY_OPERATORS\
    X(plus,+)\
    X(minus,-)\
    X(multiplies,*)\
    X(divides,/)\
    X(modulus,%)\
    X(equal_to,==)\
    X(not_equal_to,!=)\
    X(greater,>)\
    X(less,<)\
    X(greater_equal,>=)\
    X(less_equal,<=)\
    X(logical_and,&&)\
    X(logical_or,||)\
    X(bit_and,&)\
    X(bit_or,|)\
    X(bit_xor,^)

#define X(name,symbol)\
    struct name\
    {\
        template<class L,class R>\
        auto operator()(L&& l, R&& r)\
        {\
            return l symbol r;\
        }\
    };

FC_BINARY_OPERATORS
#undef X

There also exist functions unzip and unpair which are also members of mappable analogous to the Haskell unzip. For example, unpairing a vector of tuples gives a pair of vectors:

template<class L,class R>
auto unpair(std::vector<std::pair<L,R>>&& v)
{
    std::pair<std::vector<L>,std::vector<R>> out;

    for (auto& p : v)
    {
        out.first.push_back(p.first);
        out.second.push_back(p.second);
    }

    return out;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s