You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++17中以符合标准的方式交换两个std::tie调用的结果?

符合C++标准的std::swap与std::tie兼容方案问题

我一直想找符合C++标准的方法,让这段代码编译通过:

int a = 1;
int b = 2;
int c = 3;
int d = 4;

std::swap(std::tie(a, b), std::tie(c, d));

实际场景更复杂,和zip迭代器相关,但上面这段是问题核心。

这段代码编译失败的原因是:std::swap期望接收左值引用,而std::tie返回的是std::tuple<T&...>——理论上我们可以交换它间接引用的元素,哪怕这个tuple是右值。

我试过一种可行但不符合标准的方法:在std命名空间里添加std::swap的重载:

namespace std {
  template<typename... Refs>
  void swap(std::tuple<Refs&...> lhs, std::tuple<Refs&...> rhs) {
    lhs.swap(rhs);
  }
}

但这种修改std命名空间的做法不符合C++标准。

另一种思路是自定义一个包装std::tuple的类型,在自己的命名空间里添加swap重载,这样用在std::sort这类标准算法时,能通过参数依赖查找(ADL)找到对应的swap:

template<typename... Ts>
struct tuple_wrapper {
  std::tuple<Ts...> ts_;
  tuple_wrapper(Ts... ts) : ts_(ts...) {}
  // 其他实现...
};

但编写std::tuple的透明包装难度极大——和std::sort配合时经常出现大量编译错误,而且模拟std::tuple的复杂类型完全不是理想方案。

有没有简单且符合标准的解决方案?任何建议都感激不尽!


更新1

我希望在C17中解决这个问题,感谢康桓瑋指出:由于P2321提案,这段代码在C23里可以直接运行。

更新2

以下是我用到的类的代码片段:

template<typename... InputIts>
class zip_iterator {
  std::tuple<InputIts...> its_;

public:
    using iterator_category = std::random_access_iterator_tag;
    using value_type =
      std::tuple<typename std::iterator_traits<InputIts>::value_type...>;
    using difference_type = std::common_type_t<
      typename std::iterator_traits<InputIts>::difference_type...>;
    using pointer =
      std::tuple<typename std::iterator_traits<InputIts>::pointer...>;
    using reference =
      std::tuple<typename std::iterator_traits<InputIts>::reference...>;

    zip_iterator(InputIts... its) : its_(its...) {}

    reference operator*() {
      return std::apply([](auto&... its) { return std::tie(*its...); }, its_);
    }

    // 其他运算符实现...
};

我遇到的问题和reference类型有关,以及它和std::swap、std::sort的交互。

注:这个实现是参考一篇代码评审文章的思路,我只是想做个更简化的版本😅


后续发现

我发现这个问题比预想的复杂得多,涉及「代理迭代器」的相关内容。如果想了解完整的复杂性,可以参考Eric Niebler的四篇文章:

  • 《To Be or Not to Be an Iterator》
  • 《Iterators++ Part 1》
  • 《Iterators++ Part 2》
  • 《Iterators++ Part 3》

简而言之,要正确处理这类问题(比如支持仅移动类型等),需要修改标准库。目前最合理的建议是等待C++23,或者使用ranges-v3库🙈

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 01:32:22