为什么C++ 17标准没有带来部分类模板参数推导?

Kaz*_*nov 13 c++ templates template-argument-deduction argument-deduction c++17

我希望能够使用新的模板参数推导的地方之一就是构建带有自定义比较器的std::set's/std::maps /任何其他容器 - 我的目标是创建一个单行语句,这将创建一个高效的用lambda比较器设置.自C++ 11以来我能做的是:

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

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

另一种选择是:

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

它完成了工作,但1)它需要2行,并创建mycomp变量2)我需要mycomp显式传递的类型.

正如我在参考页面上看到的那样,没有一个标准容器有针对这种情况的扣除指南.不幸的是,我担心它甚至无法用当前的语言标准(C++ 17)完成,因为人们可以找到:

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

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

max*_*x66 11

在一行(C++ 17)

std::set s(std::initializer_list<int>{}, [](int a, int b) {return a > b; });
Run Code Online (Sandbox Code Playgroud)

  • @Kaznov - 工作但不是很优雅:`std :: initializer_list <int> {}`,只是为了明确`int`类型,非常难看. (9认同)

Jar*_*d42 10

作为替代方案,你仍然可以做旧 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; });
Run Code Online (Sandbox Code Playgroud)


rub*_*nvb 5

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

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

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