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

时间:2018-05-28 11:31:30

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

我希望我可以使用新模板参数演绎的其中一个地方是构建std::set' s / std::map s /任何其他带有自定义比较器的容器 - 我的目标是创建一个单行语句,它将创建一个带有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)完成,正如人们所能找到的那样:

  

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

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

4 个答案:

答案 0 :(得分:11)

在一行(C ++ 17)

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

答案 1 :(得分: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; });

答案 2 :(得分:5)

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

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

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

答案 3 :(得分:0)

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