【问题标题】:Get a tuple element in runtime在运行时获取元组元素
【发布时间】:2021-10-26 05:46:36
【问题描述】:

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

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

: 在 'constexpr std::tuple_element >::type& (* const runtime_get_func_table, std::integer_sequenceunsigned int, 0, 1, 2> >::table [3])(std::tuple&) noexcept'的实例化中: :32:53: 'constexpr typename std::tuple_elementstd::remove_reference::type>::type& runtime_get(Tuple&&, size_t) [with Tuple = >std::tuple&;类型名 std::tuple_elementstd::remove_reference::type>::type = int;类型名 std::remove_reference::type = >std::tuple; size_t = long unsigned int]' :37:37: 从这里需要 :15:35: 错误:没有匹配转换函数 'get' 到类型 '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);
}

【问题讨论】:

  • 此实现要求所有元组元素具有相同的类型,这在很大程度上违背了元组的初衷,并且您会抱怨编译器错误。
  • 对于不同的类型你需要使用回调,比如here

标签: c++ templates tuples c++17 variadic-templates


【解决方案1】:

示例代码可以重写。由于 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);
    });
}

【讨论】:

  • v 不被评估为常量表达式。 godbolt.org/z/1bb94v4Gz
  • v 不是编译时索引。它是元组元素
  • 没错。然后我不能使用 v 从元组中获取元素。或者我在元组规范中遗漏了一些东西
  • v 本身是在调用 lambda 后传递给函数的索引值处的元组元素。你不需要v = get&lt;I&gt;(t)。只是为了某些特定目的使用它
猜你喜欢
  • 2020-05-19
  • 1970-01-01
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
相关资源
最近更新 更多