C++11 way to index tuple at runtime without using switch

后端 未结 7 1126
[愿得一人]
[愿得一人] 2020-12-02 10:45

I have a piece of c++11 code similar like below:

switch(var) {
   case 1: dosomething(std::get<1>(tuple));
   case 2: dosomething(std::get<2>(tup         


        
7条回答
  •  爱一瞬间的悲伤
    2020-12-02 11:09

    I modified Oktalist's answer to make it slightly more robust:

    • make visit_at method constexpr
    • allow visitor to pass any number of arguments (visited tuple element is still required first parameter)
    • allow visitor to return a value
    • make visit_at method compatible with any std::get-compatible type (e.g., std::array)

    For completeness sake, I made it noexcept as well, though that is a mess (where is noexcept(auto) already?).

    namespace detail
    {
        template
        struct visit_impl
        {
            template
            inline static constexpr int visit(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(fun(std::get(tuple), std::forward(args)...)) && noexcept(visit_impl::visit(tuple, idx, fun, std::forward(args)...)))
            {
                return (idx == (I - 1U) ? (fun(std::get(tuple), std::forward(args)...), void(), 0) : visit_impl::visit(tuple, idx, fun, std::forward(args)...));
            }
    
            template
            inline static constexpr R visit(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(fun(std::get(tuple), std::forward(args)...)) && noexcept(visit_impl::template visit(tuple, idx, fun, std::forward(args)...)))
            {
                return (idx == (I - 1U) ? fun(std::get(tuple), std::forward(args)...) : visit_impl::template visit(tuple, idx, fun, std::forward(args)...));
            }
        };
    
        template<>
        struct visit_impl<0U>
        {
            template
            inline static constexpr int visit(Tuple const&, std::size_t, F, Args&&...) noexcept
            {
                return 0;
            }
    
            template
            inline static constexpr R visit(Tuple const&, std::size_t, F, Args&&...) noexcept(noexcept(R{}))
            {
                static_assert(std::is_default_constructible::value, "Explicit return type of visit_at method must be default-constructible");
                return R{};
            }
        };
    }
    
    template
    inline constexpr void visit_at(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(detail::visit_impl::value>::visit(tuple, idx, fun, std::forward(args)...)))
    {
        detail::visit_impl::value>::visit(tuple, idx, fun, std::forward(args)...);
    }
    
    template
    inline constexpr R visit_at(Tuple const &tuple, std::size_t idx, F fun, Args &&...args) noexcept(noexcept(detail::visit_impl::value>::template visit(tuple, idx, fun, std::forward(args)...)))
    {
        return detail::visit_impl::value>::template visit(tuple, idx, fun, std::forward(args)...);
    }
    

    DEMO (demo is not C++11 (due to laziness), but the implementation above should be)

提交回复
热议问题