【问题标题】:Merge tuple and integral instances into tuple of references将元组和整数实例合并到引用元组中
【发布时间】:2020-05-19 17:22:24
【问题描述】:

在尝试从元组和整数值的混合中构造引用元组时,我遇到了奇怪的行为。

鉴于以下情况:

struct A { int v = 1; };
struct B { int v = 2; };
struct C { int v = 3; };
A a;
std::tuple<B,C> tpl;

我正在尝试创建第三个元组,它包含对所有实例的引用,以便每个实例的 v 都可以通过它进行分配和读取。

使用模板看起来很简单

template <class Tuple, size_t... Is>
constexpr auto as_ref_impl(Tuple t, std::index_sequence<Is...>) {
    return std::tuple_cat(std::tie(std::get<Is>(t))...);
    // or
    // return std::make_tuple(std::ref(std::get<Is>(t))...);
}

template <class...Args>
constexpr auto as_ref(std::tuple<Args...>& t) {
    return as_ref_impl(t, std::index_sequence_for<Args...>{});
}

然后

auto ref_tpl = std::tuple_cat(std::tie(a), as_ref(tpl));

构建良好(在两个版本中)。

不幸的是,只有引用元组 (ref_tpl) 中源自整数值的部分可以被成功分配或读取。

我正在使用C++14gcc 9.3.0

非常欢迎任何想法或见解为什么这不起作用!

最小的工作示例:

#include <iostream>
#include <tuple>
#include <type_traits>
#include <utility>
#include <functional>

struct A { int v = 1; };
struct B { int v = 2; };
struct C { int v = 3; };
A a;
std::tuple<B,C> tpl;

template <class Tuple, size_t... Is>
constexpr auto as_ref_impl(Tuple t, std::index_sequence<Is...>) {
    //return std::tuple_cat(std::tie(std::get<Is>(t))...);
    return std::make_tuple(std::ref(std::get<Is>(t))...);
}

template <class...Args>
constexpr auto as_ref(std::tuple<Args...>& t) {
    return as_ref_impl(t, std::index_sequence_for<Args...>{});
}

int main() {
    using std::cout;

    auto ref_tpl = std::tuple_cat(std::tie(a), as_ref(tpl));

    // prints 1 2 3, as expected.
    cout << a.v << std::get<0>(tpl).v << std::get<1>(tpl).v << std::endl;

    std::get<0>(ref_tpl).v = 8; // works
    std::get<1>(ref_tpl).v = 9; // does not work
    std::get<2>(ref_tpl).v = 10; // does not work

    // should output 8 9 10 instead outputs 8 2 3
    cout << a.v << std::get<0>(tpl).v << std::get<1>(tpl).v << std::endl;

    // should output 8 9 10, instead outputs garbage.
    cout << std::get<0>(ref_tpl).v << std::get<1>(ref_tpl).v << std::get<2>(ref_tpl).v << std::endl;

    return 0;
}

【问题讨论】:

    标签: c++ templates tuples c++14 template-meta-programming


    【解决方案1】:

    这是一个简单的错字:

    constexpr auto as_ref_impl(Tuple t, std::index_sequence&lt;Is...&gt;) {

    Tuple 是按值取值的,所以制作了一个本地副本,并相对于它进行引用。

    您应该参考Tuple

    constexpr auto as_ref_impl(Tuple&amp; t, std::index_sequence&lt;Is...&gt;) {

    【讨论】:

    • 哈哈,谢谢。不敢相信我只花了整整一个小时!
    【解决方案2】:

    您的as_ref_impl 需要通过引用获取Tuple 参数,否则您将std::ref 带到本地函数。这解释了tpl 的未修改值,以及ref_tpl 中的垃圾值。

    改为这样做:

    template <class Tuple, size_t... Is>
    // note the reference parameter
    constexpr auto as_ref_impl(Tuple &t, std::index_sequence<Is...>) {      
        return std::make_tuple(std::ref(std::get<Is>(t))...);
    }
    

    这是demo

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      • 2020-02-16
      • 2023-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多