c++c++17template-meta-programminghigher-order-functionsbind-front

Mimic std::bind_front in c++17 for calling member functions


Is it somehow possible to easily mimic std::bind_front in C++17 ? (just for member function wrapping is fine)

I took a look at implementation in aiming to copy but it seems its very much implementation specific indeed.

I'm thinking a lambda wrapper or template function/object might work?

(Performance is not an issue here)


Solution

  • This can be a starting point

    template<typename F, typename ...FrontArgs>
    struct bindfronthelper
    {
        bindfronthelper(F f, FrontArgs&&...args)
            : mF{std::move(f)}
            , mFrontArg{std::forward<FrontArgs>(args)...}
        {}
    
        template<typename ...BackArgs>
        auto operator()(BackArgs&&...args) const
        {
            return std::apply(mF, std::tuple_cat(mFrontArg, std::forward_as_tuple(args...)));
        }
    
        F mF;
        std::tuple<std::decay_t<FrontArgs>...> mFrontArg;
    };
    
    template<typename F, typename ...FrontArgs>
    auto mybindfront(F f, FrontArgs&&...args)
    {
        return bindfronthelper<F, FrontArgs...>{std::move(f), std::forward<FrontArgs>(args)...};
    }
    

    https://godbolt.org/z/Tz9fen

    Written quickly and not tested well, so there might be some pitfalls in corner cases. At least it shows how this can be achieved.


    Ok I made this over complicated, here is simpler version:

    template<typename T, typename ...Args>
    auto tuple_append(T&& t, Args&&...args)
    {
        return std::tuple_cat(
            std::forward<T>(t),
            std::forward_as_tuple(args...)
        );
    }
    
    template<typename F, typename ...FrontArgs>
    decltype(auto) mybindfront(F&& f, FrontArgs&&...frontArgs)
    {
        return [f=std::forward<F>(f), 
                frontArgs = std::make_tuple(std::forward<FrontArgs>(frontArgs)...)]
                (auto&&...backArgs) 
            {
                return std::apply(
                    f, 
                    tuple_append(
                        frontArgs, 
                        std::forward<decltype(backArgs)>(backArgs)...)); 
            };
    }
    

    https://godbolt.org/z/cqPjTY

    still passes all test I've provided. I'm keeping old version since with a bit of work it can be tweaked to work with older standard of c++.