我经常写一些像
这样的片段int x,y,z; tie(x,y,z) = g[19];
例如,g
之前已声明
vector<tuple<int,int,int>> g(100);
问题是,也许以后我实际上希望x
和y
通过引用指向g
的内部,并且重构是丑陋的,例如。
int &x = get<0>(g[19]);
int &y = get<1>(g[19]);
int &z = get<2>(g[19]);
或有时甚至更糟,例如,如果访问是一个更复杂的表达式
tuple<int,int,int> &p = g[19]; // if the rhs was actually more complicated
int &x = get<0>(p);
int &y = get<1>(p);
int &z = get<2>(p);
是否有更好的重构,更多的是分配方式(...)?
我理解的困难是参考文献坚持要初始化exactly at their declaration。所以,换句话说,有没有办法在c ++中使用tie
- 类似于多变量初始化的语法(这也会使早期的非参考用法更清晰)?
答案 0 :(得分:6)
您可以使用一个功能自动化它,这样您就不必输入3行(或更多行):
template <class... Ts, std::size_t... Is, class Tuple>
decltype( auto ) tie_from_specified( std::index_sequence<Is...>, Tuple& tuple )
{
return std::tuple<Ts...>{ std::get<Is>( tuple )... };
}
template <class... Ts, class Tuple>
decltype( auto ) tie_from( Tuple& tuple )
{
return tie_from_specified<Ts...>( std::make_index_sequence<sizeof...( Ts )>{}, tuple );
}
用法是:
int x{ 2 };
std::tuple<int, int&, int> g19( 1, x, 3 );
// new tuple: ref to get<0>( g19 ), value of get<1>( g19 ), ref to get<2>( g19 )
auto t0{ tie_from<int&, int, int&>( g19 ) };
// new tuple: ref to get<0>( g19 ), ref to get<2>( g19 )
auto t1{ tie_from_specified<int&, int&>( std::index_sequence<0, 2>{}, g19 ) };
答案 1 :(得分:5)
幸运的是,C ++ 17有一个解决这个问题的解决方案structured binding declaration。甚至可以改进非参考界面。
auto[x, y, z] = g[i];
上面的行声明了x,y,z,并使用g[i]
的值初始化它们。它不仅更清洁,而且对于构造昂贵的类型来说可能更有效。
要获得对g[i]
成员的引用,可以写
auto& [x, y, z] = g[i];
答案 2 :(得分:0)
您可以编写一个结构来存储引用:
struct vector3d
{
vector3d(std::tuple<int, int, int>& tuple)
: x(std::get<0>(tuple)),
y(std::get<1>(tuple)),
z(std::get<2>(tuple))
{}
int& x;
int& y;
int& z;
};
然后像这样使用它:
vector3d vec(g[6]);
// do sth with vec.x or vec.y or vec.z or all together :)