为类提供类似元组的结构化绑定访问 [英] Providing tuple-like structured binding access for a class

查看:59
本文介绍了为类提供类似元组的结构化绑定访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为类支持类似元组的结构化绑定访问.为简单起见,在本文的其余部分中,我将使用以下类:

I'm trying to support tuple-like structured binding access for a class. For simplicity, I'll use the following class in the rest of this post:

struct Test
{
    int v = 42;
};

(我知道该类支持开箱即用的结构化绑定,但让我们假设它不支持.)

(I'm aware that this class supports structured bindings out of the box but let's assume it does not.)

启用对元组的访问权限 Test的成员,我们必须专门处理 std :: tuple_size std :: tuple_element :

To enable tuple-like access to the member of Test, we must specialize std::tuple_size and std::tuple_element:

namespace std
{

template<>
struct tuple_size<Test>
{
    static const std::size_t value = 1;
};

template<std::size_t I>
struct tuple_element<I, Test>
{
    using type = int;
};

}

最后我们需要的是 Test :: get< i> Test 中的函数 get< i>(Test)>的名称空间.让我们实现后者:

And the last part we need is either Test::get<i> or a function get<i>(Test) in Test's namespace. Let's implement the latter:

template<std::size_t I>
int get(Test t)
{
    return t.v;
}

这有效.但是,我想返回对 Test 成员的引用,例如,就像 std :: get(std :: tuple)一样.因此,我按如下方式实现 get :

This works. However, I would like to return a reference to Test's member, just like std::get(std::tuple), for example. Therefore, I implement get as follows:

template<std::size_t I>
int& get(Test& t)
{
    return t.v;
}

template<std::size_t I>
const int& get(const Test& t)
{
    return t.v;
}

但是,在此版本中,以下代码

With this version, however, the following code

auto test = Test{};
auto [v] = test;

产生错误(GCC 7.1):

produces an error (GCC 7.1):

"std :: tuple_element< 0,Test> :: type&类型的绑定引用{aka int&}"改为"const int"会丢弃限定符

binding reference of type ‘std::tuple_element<0, Test>::type& {aka int&}’ to ‘const int’ discards qualifiers

因此,似乎为结构化绑定选择了 get< i>(const Test&)重载.由于此重载返回 const int& ,并且 v 的行为类似于对 int 的非 const 引用,因此,代码无法编译.

So it seems as if the get<i>(const Test&) overload is selected for the structured binding. Since this overload returns a const int&, and v acts like a non-const reference to int, the code fails to compile.

根据,但是,行 auto [v] =测试; 应该大致等同于

According to this, however, the line auto [v] = test; should be roughly equivalent to

auto e = test;
std::tuple_element<0, Test>::type& v = get<0>(e)

起作用,因为它使用了 get< i>(Test&)重载.

Which does work since it uses the get<i>(Test&) overload.

关于为什么我的 get 实现不适用于结构化绑定的任何想法?

Any ideas on why my implementation of get does not work for structured bindings?

推荐答案

问题是 auto [v] 是非引用声明,因此复制了 test 并将 test 的副本作为xvalue传递给 get .

The problem is that auto [v] is a non-reference declaration, so test is copied and the copy of test is passed to get as an xvalue.

因此,您需要添加一个右值限定的get:

So you need to add an rvalue qualified get:

template<std::size_t I>
int&& get(Test&& t)
{
    return std::move(t.v);
}

这篇关于为类提供类似元组的结构化绑定访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆