Feed template function element from tuple at runtime?

前端 未结 2 538
失恋的感觉
失恋的感觉 2021-01-20 19:37

In C++ I have a tuple with some elements in it:

std::tuple  my_tuple(3, \'q\');

And some template function that perfectly

相关标签:
2条回答
  • 2021-01-20 19:53

    n being a runtime value, it can't be used to instanciate a template at compile-time. Your switch works because you manually instanciate each std::get<N>, and wire them to the corresponding runtime value.

    But yeah, it's a bit of a chore to write that braindead switch tree. Why not let the compiler generate the boilerplate with a bit of TMP ?

    #include <tuple>
    #include <cassert>
    #include <iostream>
    
    template <class T>
    void my_function(T);
    
    // Test specialisations to see what's going on
    template <> void my_function(int i) { std::cout << "int " << i << '\n'; }
    template <> void my_function(char c) { std::cout << "char " << c << '\n'; }
    
    namespace detail {
        // Available in std in C++14
        template <bool P, class T>
        using enable_if_t = typename std::enable_if<P, T>::type;
    
        // Mockup function signature to pick up the call when enable_if shunts
        template <std::size_t N, class T = void>
        void callMyFunc(T&&, ...) {
            assert(!"Index not in range !");
        }
    
        // "Simple" recursive solution, removes itself from the overload set
        // to stop recursion
        template <std::size_t N, class... Ts,
            class = enable_if_t<N < sizeof...(Ts), void>>
        void callMyFunc(std::tuple<Ts...> &tuple, std::size_t n) {
            return n == N
                ? my_function(std::get<N>(tuple))
                : callMyFunc<N + 1>(tuple, n);
        }
    }
    
    // Tiny user-friendly wrapper
    template <class... Ts>
    void callMyFunc(std::tuple<Ts...> &tuple, std::size_t n) {
        detail::callMyFunc<0u>(tuple, n);
    }
    
    int main(int, char**) {
        std::tuple <int, char> my_tuple(3, 'q');
    
        // Success.
        callMyFunc(my_tuple, 0u);
        callMyFunc(my_tuple, 1u);
    
        return 0;
    }
    
    0 讨论(0)
  • 2021-01-20 19:57

    Following may help:

    template <typename T> struct caller;
    
    template <typename... Ts> struct caller<std::tuple<Ts...>>
    {
        template <typename F>
        void operator() (F f, std::tuple<Ts...>& t, int n)
        {
            (*this)(f, t, n, std::index_sequence_for<Ts...>());
        }
    private:
        template <typename F, std::size_t ... Is>
        void operator() (F f, std::tuple<Ts...>& t, int n, std::index_sequence<Is...>)
        {
            std::function<void(F, std::tuple<Ts...>&)> fs[] = { &helper<F, Is>... };
            fs[n](f, t);
        }
    
        template <typename F, std::size_t I>
        static void helper(F f, std::tuple<Ts...>& t)
        {
            f(std::get<I>(t));
        }
    
    };
    
    template <typename F, typename T>
    void call(F f, T& t, int n)
    {
        caller<T>()(f, t, n);
    }
    

    Live example

    0 讨论(0)
提交回复
热议问题