Apply the first valid function of a set of N functions

前端 未结 5 2038
南旧
南旧 2020-12-10 06:52

This previous answer shows how to apply function based on the validity of a call: here. However, it applies to two functions. I was wondering if the concept could be general

5条回答
  •  情歌与酒
    2020-12-10 07:11

    The syntax you are using is kind of awkward, since you have to know exactly how many functions you have. Combined with Piotr Skotnicki's solution, this solves that problem:

    // Would be a local class except for the fact that it needs
    // to have templates, thus can't be local to the function.
    template
    class apply_first_f final {
    public:
        apply_first_f(Fs&&... fs)
            : fs_{ std::forward(fs)... }
        {}
    
        template
        decltype(auto) operator()(Args&&... args) const
        {
            return apply_impl(std::make_index_sequence{}, std::forward_as_tuple(std::forward(args)...));
        }
    private:
        std::tuple...> fs_;
    
        template
        decltype(auto) apply_impl(std::index_sequence, Args&& args) const
        {
            return apply_on_validity_impl(
                0,
                std::integral_constant{},
                std::make_index_sequence{},
                std::tuple_cat(
                    std::forward_as_tuple(std::get(fs_)...),
                    std::forward(args)
                )
            );
        }
    };
    
    template
    auto make_apply_first_valid_f(Fs&&... fs)
    {
        return apply_first_f{ std::forward(fs)... };
    }
    

    And the function can be used like so:

    make_apply_first_valid_f(f1, f2, f3)(args);
    

    DEMO (adapted from Piotr's demo)

    Using it with Piotr's C++ 1z example requires just a small change:

    template
    class apply_first_f final {
        // ...
        template
        decltype(auto) apply_impl(std::index_sequence, Args&& args) const
        {
            return apply_on_validity_impl(
                /* 0, */
                /* std::integral_constant{}, */
                std::make_index_sequence{},
                std::tuple_cat(
                    std::forward_as_tuple(std::get(fs_)...),
                    std::forward(args)
                )
            );
        }
        // ...
    };
    

提交回复
热议问题