为类提供类似元组的结构化绑定访问 [英] Providing tuple-like structured binding access for a class
问题描述
我正在尝试为类支持类似元组的结构化绑定访问.为简单起见,在本文的其余部分中,我将使用以下类:
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屋!