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

为什么范围算法在比较器参数之后有投影参数?

如何解决为什么范围算法在比较器参数之后有投影参数?

C++20 范围算法支持投影,显然与 STL 算法一样,它们支持自定义比较器。

但让我感到困惑的是投影和比较器的顺序。

我的“问题”(更令人烦恼的是,我将很快学会使用这种参数顺序)是它打破了从左到右的代码流。

考虑下面的代码(很抱歉它不是很短,但这就是重点,以表明在实际代码中参数的顺序会使代码在变量命名时更难阅读 不是 2 个字母长):

struct PointyPoint {
  int x;
  int y;
};

struct Item {
  std::string name;
  PointyPoint location;
};

//...

  std::ranges::sort(
      items,[](const PointyPoint &a,const PointyPoint &b) {
        return std::tie(a.x,a.y) < std::tie(b.x,b.y);
      },&Item::location);

我对这段代码的问题是,我认为如果投影在 lambda(比较器)之前看起来会更好。

完整代码godbolt

我认为该订单被选中的原因:

  • STL 算法通常将比较器作为第三个参数(在迭代器之后的第一个参数),因此它是匹配的
  • 也许自定义比较器比投影更常见,因此避免需要提供该参数

解决方法

我相信你自己已经提到了其中的原因,但让我加强你的观点:

  • 将预定范围代码移植到 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); Intent intent = sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent(); //String startDir = "Android"; //String startDir = "Download"; // Not choosable on an Android 11 device //String startDir = "DCIM"; //String startDir = "DCIM/Camera"; // replace "/","%2F" //String startDir = "DCIM%2FCamera"; // String startDir = "Documents"; String startDir = "Android/data"; Uri uri = intent.getParcelableExtra("android.provider.extra.INITIAL_URI"); String scheme = uri.toString(); Log.d(TAG,"INITIAL_URI scheme: " + scheme); scheme = scheme.replace("/root/","/document/"); startDir = startDir.replace("/","%2F"); scheme += "%3A" + startDir; uri = Uri.parse(scheme); intent.putExtra("android.provider.extra.INITIAL_URI",uri); Log.d(TAG,"uri: " + uri.toString()); ((Activity) context).startActivityForResult(intent,REQUEST_ACTION_OPEN_DOCUMENT_TREE); return; } 应该很​​简单。假设您有一个现有的

    <ranges>

    并希望将其转换为 std::sort(data.begin(),data.end(),std::greater<>{}); 算法调用。想象一下你必须和

    一起去
    <ranges>

    这确实构成了阻碍轻松迁移的负担。与实际订购,您可以将第一个版本更改为

    std::ranges::sort(data,std::identity{},std::greater<>{});
    
  • 使用标准比较的摩擦非常低,因此如果您需要投影,很容易在前面添加 std::ranges::sort(data,std::greater<>{}); 。诚然,您可以对 std::less<>{} 说同样的话,但这并不排除第一点。

最后,this document 中的理性也可能对这个主题有所帮助:

对于可以选择接受函数/谓词(例如转换、排序)的算法,投影参数跟在函数/谓词之后。没有算法重载允许用户在不指定谓词的情况下指定投影,即使默认值就足够了。这是为了减少重载次数,同时避免任何潜在的歧义。

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