在运行时获取元组元素

Get a tuple element in runtime

阅读如何在运行时访问元组元素,我发现了以下实现 getting-tuple-elements-with-runtime-index

我自己用 gcc 11.2 试过了。我调用 API 来检索元组,但出现以下错误

: In instantiation of 'constexpr std::tuple_element >::type& (* const runtime_get_func_table, std::integer_sequenceunsigned int, 0, 1, 2> >::table [3])(std::tuple&) noexcept': :32:53: required from 'constexpr typename std::tuple_elementstd::remove_reference::type>::type& runtime_get(Tuple&&, size_t) [with Tuple = >std::tuple&; typename std::tuple_elementstd::remove_reference::type>::type = int; typename std::remove_reference::type = >std::tuple; size_t = long unsigned int]' :37:37: required from here :15:35: error: no matches converting function 'get' to type 'const get_func_ptr' {aka >'int& (* const)(class std::tuple&) noexcept'} 15 | static constexpr get_func_ptr table[std::tuple_size::value]={

找到下面的代码(live demo)

#include <tuple>
#include <utility>
#include <type_traits>
#include <stdexcept>

template<
  typename Tuple,
  typename Indices=std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct runtime_get_func_table;

template<typename Tuple,size_t ... Indices>
struct runtime_get_func_table<Tuple,std::index_sequence<Indices...>>{
    using return_type=typename std::tuple_element<0,Tuple>::type&;
    using get_func_ptr=return_type (*)(Tuple&) noexcept;
    static constexpr get_func_ptr table[std::tuple_size<Tuple>::value]={
        &std::get<Indices>...
    };
};

template<typename Tuple,size_t ... Indices>
constexpr typename
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::get_func_ptr
runtime_get_func_table<Tuple,std::index_sequence<Indices...>>::table[std::tuple_size<Tuple>::value];

template<typename Tuple>
constexpr
typename std::tuple_element<0,typename std::remove_reference<Tuple>::type>::type&
runtime_get(Tuple&& t,size_t index) {
    using tuple_type=typename std::remove_reference<Tuple>::type;
    if(index>=std::tuple_size<tuple_type>::value)
        throw std::runtime_error("Out of range");
    return runtime_get_func_table<tuple_type>::table[index](t);
}

int main() {
    std::tuple<int ,char,float> t;
    auto  a =  runtime_get(t,0);
}

示例代码可以重写。由于多个 return 类型在 C++ 中是不可能的,因此您必须通过作为参数传递的 lambda 函数来获取它。评论里的那个人也提到了同样的方法

#include <tuple>
#include <utility>
#include <type_traits>
#include <stdexcept>


template<
  typename Tuple,
  typename F,
  typename Indices=std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct runtime_get_func_table;

template<typename Tuple, typename F, size_t I>
    void applyForIndex(Tuple& t, F f) {
        f(std::get<I>(t));
    }

template<typename Tuple, typename F, size_t ... Indices>
struct runtime_get_func_table<Tuple,F,std::index_sequence<Indices...>>{
    using FuncType = void(*)(Tuple&, F);
    static constexpr FuncType table[]={
        &applyForIndex<Tuple, F, Indices>...
    };
};

template<typename Tuple, typename F>
void runtime_get(Tuple& t,size_t index, F f) {
    using tuple_type=typename std::remove_reference<Tuple>::type;
    if(index>=std::tuple_size<tuple_type>::value)
        throw std::runtime_error("Out of range");
    runtime_get_func_table<tuple_type, F>::table[index](t, f);
}

int main() {
    std::tuple<int ,char, float> t(10, 's', 10.2);
    runtime_get(t, 0, [] (auto& v) {
      // Do something v = get<0>(t);
    });
}