【发布时间】:2017-08-15 18:17:51
【问题描述】:
我正在尝试支持类的类似元组的结构化绑定访问。为简单起见,我将在本文的其余部分使用以下类:
struct Test
{
int v = 42;
};
(我知道这个类支持开箱即用的结构化绑定,但我们假设它不支持。)
到enable tuple-like access到Test的成员,我们必须专门化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> 或Test 命名空间中的函数get<i>(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::type& {aka int&}’到‘const int’的绑定引用丢弃了限定符
因此,似乎为结构化绑定选择了 get<i>(const Test&) 重载。由于此重载返回一个const int&,而v 的行为类似于对int 的非const 引用,因此代码无法编译。
然而,根据this,auto [v] = test; 应该大致相当于
auto e = test;
std::tuple_element<0, Test>::type& v = get<0>(e)
哪个确实工作,因为它使用get<i>(Test&) 重载。
关于为什么我的get 实现不适用于结构化绑定的任何想法?
【问题讨论】:
-
您忘记了“在这些初始化表达式中,如果实体
e的类型是左值引用,则e是左值,否则为 xvalue”。 -
@Barry 引用的类型由初始化器的值类别确定,它是一个左值(因为它最终使用
const &重载)。不确定您希望如何诊断... -
@T.C.是的,在你回复之前删除了我的评论:)
标签: c++ c++17 structured-bindings