微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 使用std :: tie初始化多个引用

我想通过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交集引起的所有奇怪的怪癖等等.

原文地址:https://www.jb51.cc/c/110603.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐