c++ - 需要对 std::tuple(即 std::get<E>)进行非常量索引访问的 Eloquent 解决方案

标签 c++ tuples variadic

tl;dr 有什么简单的方法可以使用 std::get使用非常量索引?


我知道这个问题已被问过很多次,但所提出的解决方案似乎都不是特别简单、 Eloquent 或适合我的情况。

我正在寻找的是:一种使用 std::get<E> 的无痛方式, 其中E是任何表达式,为了返回 T&Tstd::get 中已知存在(即,对于范围异常是安全的,因此绕过了安全范围 std::tuple<T> ) .

问题似乎是编译器需要知道 std::get 的类型的 return ,但我将手动输入数据及其类型,不需要确定类型。 (也许 auto 可以用在什么地方?)

我想要这样做的原因可以通过以下片段来解释。我正在尝试创建一个数据容器类,您可以使用初始化列表来填充它。


  1. 要点:用于允许元组的模拟初始化程序列表。

    template<class... T>
    class Point {
    public:
        std::tuple<T...> get() const { return data; }
        Point(T... t) {
            data = std::tuple<T...>(t...);
        }
    private:
        std::tuple<T...> data;
    };
    
  2. 数据:设计用于在 std::tuple 中保存动态数据量的 std::vector<T> , 其中T是一组用户定义类型中的每一个。

    template<typename... T>
    class Data {
    public:
        Data(std::initializer_list<Point<T...>> data = {{}})
            : columns(sizeof...(T))
        {
            // ???
        }
    private:
        byte columns;
        std::tuple<std::vector<T>...> datas;
    };
    
  3. 结合起来,这应该允许这种简单的格式用于快速数据输入(或 future 来自外部源的数据流):

    int main() {
        Data<char, int, float> {
            { 'A', 1, 3.14 } ,
            { 'B', 2, 6.28 }
        };
    
        return 0;
    }
    

这些都是为了稍后移植到一个充满有用扩展的库中,这些扩展以使非程序员轻松输入数据和公式的方式处理数据而无需大惊小怪。公式的一半有效,但由于 std::get 的限制,我在这一半上仍然遇到问题:

for (auto d : data) {
    for (int i = 0; i < columns; ++i) {
        std::get<i>(datas).push_back(std::get<i>(data));
        // doesn't work; std::get<N> requires const N to know return type to use push_back
    }
}

我发现这真的很令人沮丧,因为大多数情况下都是如此。我无法将 datas 替换为 std::array s 或 std::vector s因为多种类型;我想避免使用 boost尽管boost::any ; switch (column) { case 0: std::get<0>(...)... }可用于模仿动态 std::get ,但如果我不能为每个可能的第 n 列手动输入一个案例;仅仅为了这个小目的而对新的容器类型进行元编程的努力似乎不必要地过于复杂;似乎没有其他快速修复解决方案足以应对这些特定情况。

最佳答案

tl;dr is there any easy way to use std::get with a non-const index?

不,因为根本没有一种方法可以将它与非常量索引一起使用。既不难也不容易使用。

但是你可以让你的构造函数像

Data(std::initializer_list<Point<T...>> data)
{
  for (auto&& d : data)
  {
    tup_to_vectup(std::make_index_sequence<sizeof...(T)>{},
      datas, d.data);
  }
}

有像这样的小 helper

template<std::size_t ... I, class VecTup, class Tup>
void tup_to_vectup(std::index_sequence<I...>, VecTup&& vt, Tup&& t)
{
  int a[] = {
    0, (std::get<I>(vt).push_back(std::get<I>(t)), 0)...
  };
  (void)a;
}

因为这里实际上不需要非常量索引。您的类模板参数 ...T 在编译时确定索引。您只需将它们转换为索引序列并使用它来迭代您的元组。

关于c++ - 需要对 std::tuple(即 std::get<E>)进行非常量索引访问的 Eloquent 解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38319735/

相关文章:

tuples - 使用函数在 Julia 中重复值

c++ - 限制可变参数函数模板仅接受一个可变参数类模板的嵌套可变参数类模板的变体?

C++:在点后提取字符串

C++如何调用子类函数

c++ - 如何使用 MPI_Type_create_subarray?

C++ 自定义时间日期结构到 utc 纪元

python - 如果元组包含标点符号,如何从列表中删除元组

where 子句中的 Swift 元组

javascript - 在 Javascript 的可变参数函数中调用可变参数函数?

c++ - 可变参数宏,用于从未知参数集合生成字符串 vector