我正在尝试为类支持类似元组的结构化绑定访问。为简单起见,我将在本文的其余部分使用以下类:
struct Test
{
int v = 42;
};
(我知道这个类支持开箱即用的结构化绑定,但我们假设它没有。)
要Test
成员enable tuple-like access,我们必须专注std::tuple_size
和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>
或get<i>(Test)
命名空间中的函数Test
。让我们实现后者:
template<std::size_t I>
int get(Test t)
{
return t.v;
}
这很有效。但是,我想返回对Test
成员的引用,例如std::get(std::tuple)
。因此,我按如下方式实施get
:
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;
}
但是,对于此版本,以下代码
auto test = Test{};
auto [v] = test;
产生错误(GCC 7.1):
类型'std :: tuple_element&lt; 0,Test&gt; :: type&amp;的绑定引用{aka int&amp;}'到'const int'丢弃限定符
因此,似乎为结构化绑定选择了get<i>(const Test&)
重载。由于此重载返回const int&
,而v
的行为类似于对const
的非int
引用,因此代码无法编译。
然而,根据this,行auto [v] = test;
应大致相当于
auto e = test;
std::tuple_element<0, Test>::type& v = get<0>(e)
工作,因为它使用get<i>(Test&)
重载。
关于为什么我的get
实现不适用于结构化绑定的任何想法?
答案 0 :(得分:6)
问题是auto [v]
是非参考声明,因此复制test
并将test
的副本作为xvalue传递给get
。
所以你需要添加一个rvalue限定的get:
template<std::size_t I>
int&& get(Test&& t)
{
return std::move(t.v);
}