meta icon indicating copy to clipboard operation
meta copied to clipboard

runtime meta::visit would be nice

Open gabyx opened this issue 7 years ago • 3 comments

I needed a runtime visitor analogue to meta::for_each:

using List = meta::list<int,double,float,double>;
std::size_t index = 2
meta::visit<List>(2, [](auto type){ std::cout << "called with type==double"; });

I came up with this, which builds a static function pointer map:


namespace meta
{
    namespace details
    {
        template<typename Func, typename Type>
        struct Wrapper
        {
            static void invoke(Func f) { f(Type{}); }
        };

        template<typename Func, typename List> struct visit;

        template<typename Func, typename... Types>
        struct visit<Func, meta::list<Types...>>
        {
            static constexpr auto makeMap()
            {
                using FuncPtr = decltype(&Wrapper<Func, void>::invoke);
                using Array   = std::array<FuncPtr, sizeof...(Types)>;
                // Build member function pointers.
                return Array{&Wrapper<Func, Types>::invoke...};
            }
        };
    }  // namespace details

    //! Apply the function `Func` with the type
    //! in the `List` at position `index`.
    template<typename List, typename Func>
    void visit(std::size_t index, Func&& f)
    {
        using F            = decltype(std::forward<Func>(f));  // Define either an lvalue, or rvalue;
        constexpr auto map = details::visit<F, List>::makeMap();
        if(index >= map.size()){ throw std::out_of_range();}
        map[index](std::forward<Func>(f));
    }

}  // namespace meta

Works like a charm for example with an rvalue lambda:

MY_TEST(MetaProgramming, Test1)
{
    using List = meta::list<int, double, short>;
    int b      = -1;
    meta::visit<List>(2,
                      [&](auto type) {
                          using T = decltype(type);
                          if constexpr(std::is_same<T, short>{})
                          {
                              b = 2;
                          }
                      });
    ASSERT_EQ(b, 2) << "Meta Visit failed!";
}

gabyx avatar Aug 06 '18 21:08 gabyx

Could we add this to the library? Is a PR welcome?

gabyx avatar Feb 02 '19 11:02 gabyx

https://wandbox.org/permlink/HYZ4BSj4IpBqMwIn

gabyx avatar Feb 02 '19 12:02 gabyx

See #73

gabyx avatar Feb 14 '19 23:02 gabyx