【问题标题】:Why didn't the C++17 standard bring partial class template argument deductions? [duplicate]为什么 C++17 标准没有带来部分类模板参数推导? [复制]
【发布时间】:2018-05-28 11:31:30
【问题描述】:

我希望能够使用新模板参数推导的地方之一是构造 std::set's / std::maps / 任何其他带有自定义比较器的容器 - 我的目标是创建一个-line 语句,它将使用 lambda 比较器创建一个有效的集合。 从 C++11 开始我能做的是:

std::set<int, std::function<bool(int, int)>> s([](int a, int b) {return a > b;});

但由于它使用std::function,它明显变慢了。

另一种选择是:

auto mycomp = [](int a, int b) {return a > b; };
std::set<int, decltype(mycomp)> s(mycomp);

它完成了工作,但是 1) 它需要 2 行,并创建 mycomp 变量 2) 我需要明确传递 mycomp 的类型。

正如我在参考页面上所读到的,标准容器都没有针对这种情况的推论指南。不幸的是,恐怕它甚至不能用当前的语言标准(C++17)来完成,正如人们可以发现的那样:

类模板参数推导仅在不存在模板参数列表时执行。如果指定了模板参数列表,则不会进行推导。

这背后的原因是什么?为什么他们不允许部分论证推论?我想它有一些我忽略的问题,但在我看来它会很有帮助。

【问题讨论】:

  • 部分扣除先在提案中,但已被删除。见c17-class-template-partial-deduction
  • @Kaznov:“我的目标是创建一行语句,这将使用 lambda 比较器创建有效的集合。” ...为什么这是你的目标?仅创建具有 operator() 重载的结构有什么问题?为什么您必须(甚至想要)使用 lambda?

标签: c++ templates c++17 template-argument-deduction


【解决方案1】:

一行代码 (C++17)

std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });

【讨论】:

  • 谢谢!我不知道这个构造函数的存在。好吧,它解决了容器的问题。
  • @Kaznov - 有效但不是很优雅:std::initializer_list&lt;int&gt;{},只是为了明确int 类型,非常丑陋。
【解决方案2】:

作为替代方案,您仍然可以使用旧的make_xxx

template <typename T, typename COMP>
std::set<T, COMP> make_set(COMP comp)
{
    return std::set<T, COMP>{comp};
}


auto s = make_set<int>([](int a, int b) {return a > b; });

【讨论】:

    【解决方案3】:

    您应该做的是编写一个比较器函子类型,因此在使用您的集合时不需要代理它。这将是更多的代码行(暴行!),但几乎在各个方面都更好:

    struct MyComparator
    {
        bool operator()(int a, int b) const { ...; }
    };
    using MySet = std::set<int, MyComparator>;
    

    从那时起,您只需在需要的地方创建自定义排序集。

    【讨论】:

    • 我知道这是解决这个问题的最好方法,但我一直在寻找最紧凑的方法。
    • @Kaznov:为什么需要紧凑?在模板特化中间有一个大的 lambda 不会让你的代码更容易阅读。这种不那么“紧凑”的方式比 lambda 更容易阅读。
    • 我一直在寻找最快的方法,将其用于算法竞赛。那里你不在乎代码长什么样,越短越好。
    【解决方案4】:

    由于存在具有默认值的模板参数时会带来歧义。此外,对于可变参数模板。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-25
      • 2017-12-26
      • 1970-01-01
      • 2020-01-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2017-12-30
      相关资源
      最近更新 更多