我想通过std :: tie(或std :: forward_as_tuple)-see玩具代码,通过std :: tuple初始化从函数返回的多个引用.
#include <tuple> #include <iostream> class Foo { public: Foo () : m_memberInt(5),m_anotherMemberInt(7) {} void IncrementMembers() {++m_memberInt; ++m_anotherMemberInt;} std::tuple<int &,int &> GetMembers() {return std::tie(m_memberInt,m_anotherMemberInt);} private: int m_memberInt; int m_anotherMemberInt; }; int main() { Foo foo; // Can't have dangling references. // int &x,&y; // std::tie(x,y) = foo.GetMembers(); std::tuple<int &,int &> tmpTuple = foo.GetMembers(); int &x = std::get<0>(tmpTuple); int &y = std::get<1>(tmpTuple); std::cout << x << " " << y << std::endl; foo.IncrementMembers(); std::cout << x << " " << y << std::endl; return 0; }
上面的解决方案有效,但是临时std :: tuple和多个std :: gets很烦人,如果可能的话,能够避免这种情况会非常好(比如返回非引用时).
问题是我们不能有悬空引用,所以不能事先初始化变量.是否有一些C 11 / C 14的魔法允许我初始化引用,因为我调用std :: tie?或者上面是唯一的解决方案?
解决方法
在C 17中,结构化绑定为您编写代码.
std::tuple<int &,int &> tmpTuple = foo.GetMembers(); int &x = std::get<0>(tmpTuple); int &y = std::get<1>(tmpTuple);
大致相同
auto&[x,y] = foo.GetMembers();
(我的C 17代码中可能有轻微的语法错误,我缺乏经验,但你明白了.)
您可以在C 14中使用延续传递样式和适配器执行类似的操作:
template<class Tuple> struct continue_t { Tuple&& tuple; using count = std::tuple_size<std::remove_reference_t<Tuple>>; using indexes = std::make_index_sequence<count{}>; template<std::size_t...Is> auto unpacker(std::index_sequence<Is...>) { return [&](auto&& f)->decltype(auto){ using std::get; // ADL enabled return decltype(f)(f)( get<Is>(std::forward<Tuple>(tuple))... ); }; }; template<class F> decltype(auto) operator->*( F&& f )&& { auto unpack = unpacker( indexes{} ); return unpack( std::forward<F>(f) ); } }; template<class F> continue_t<F> cps( F&& f ) {return {std::forward<F>(f)};}
哪个模数错字,给你:
cps(foo.GetMembers()) ->*[&](int& x,int&y) { std::cout << x << " " << y << std::endl; foo.IncrementMembers(); std::cout << x << " " << y << std::endl; }; return 0;
这很奇怪. (注意,cps支持返回对或std :: arrays以及任何“类似tuple”的函数).
实际上没有更好的方法来处理这种结构化绑定,其中有一个原因是添加到C 17.
一个可怕的预处理程序黑客可能写得如下:
BIND_VARS( foo.GetMembers(),x,y );
但是代码量会很大,我所知道的编译器没有让你调试会产生的混乱,你会得到预处理器和C交集引起的所有奇怪的怪癖等等.