【问题标题】:Deduce type of Compare for std::set from constructor arguments从构造函数参数推断 std::set 的比较类型
【发布时间】:2020-06-25 09:01:32
【问题描述】:

我想在使用自定义比较声明 std::set 时编写更简单的语法:

auto s = std::set({1,3,7,9,2,4},[](int a,int b){return a>b;});

但它不能开箱即用。 CLang 产生:

/Users/kyb/devel/untitled3/main.cpp:13:14: error: ambiguous deduction for template arguments of 'set'
    auto s = set({1,3,7,9,2,4},[](int a,int b){return a>b;});
             ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/set:531:5: note: candidate function [with _Key = int, _Compare = (lambda at /Users/kyb/devel/untitled3/main.cpp:13:32), _Allocator = std::__1::allocator<int>]
    set(initializer_list<value_type> __il, const value_compare& __comp = value_compare())
    ^
/Library/Developer/CommandLineTools/usr/include/c++/v1/set:547:5: note: candidate function [with _Key = int, _Compare = std::__1::less<int>, _Allocator = (lambda at /Users/kyb/devel/untitled3/main.cpp:13:32)]
    set(initializer_list<value_type> __il, const allocator_type& __a)
    ^
1 error generated.

有一个窍门——入侵演绎指南:

namespace std::__1{
    template<typename T, typename Compare> set(initializer_list<T> il, const Compare&comp) -> set<T,Compare>;
}

产生警告:

warning: inline namespace reopened as a non-inline namespace

我相信有办法以更干净的方式做到这一点。

clang --version:

Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
/V/l/n/new-diag-commands ❯❯❯

【问题讨论】:

  • 这样好吗? auto com = [](int a, int b) {return a &gt; b; }; std::set&lt;int, decltype(com)&gt; s({1,3,7,9,2,4 }, com);。即使使用 clang-7:godbolt.org/z/Zc9WxU 也会编译
  • Works for me 用于 msvc clang 和 gcc。您是否启用了允许这样做的 C++17?投票以“无法复制”结束。
  • @MarekR 正如我在回答中所指出的,这是 Clang 9 之前版本中的一个 clang 缺陷。
  • @MarekR 这很奇怪,according to wandbox 在 clang 9 之前的所有 clang 版本上都失败了。

标签: c++ templates c++17 stdset


【解决方案1】:

我相信有办法以更干净的方式做到这一点。

您上面的代码 sn-p 不应被 clang 拒绝,这是由 [associative.reqmts]/151 [emphasis mine] 管理的:

关联容器的推导指南不参与 如果以下任何一项为真,则在重载决议中:

  • (15.1) 它有一个InputIterator 模板参数,并且为该参数推导出一个不符合输入迭代器条件的类型。
  • (15.2) 它有一个Allocator 模板参数,并且为该参数推断出不符合分配器条件的类型
  • (15.3) 它有一个 Compare 模板参数,并且为该参数推导出一个有资格作为分配器的类型。

自 Clang 9 起,此问题已得到纠正。


[1] N4659: March 2017 post-Kona working draft/C++17 DIS.

【讨论】:

  • 是的。我刚才注意到了。
猜你喜欢
  • 2020-10-17
  • 2022-01-26
  • 1970-01-01
  • 2021-05-30
  • 2019-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-08-06
相关资源
最近更新 更多