C++ implicit/explicit 模板方法专业化问题

C++ implicit/explicit template method specialization issue

我在调用函数时遇到问题:

namespace Sort {

    enum Type {
        insertion, selection, merge
    };

    template <class Elem = int, class Container = std::vector<Elem>>
    void sort(std::shared_ptr<Container> vectorPointer,
              std::function<bool(Elem, Elem)> comparator = std::less<Elem>(),
              Type type = selection) {

        switch (type) {
            case insertion:
                insertionSort(vectorPointer, comparator);
            case selection:
                selectionSort(vectorPointer, comparator);
            case merge:
                mergeSort(vectorPointer, comparator);
        }
    }
}

当我这样称呼它时:

std::shared_ptr<std::vector<int>> intVector;

Sort::sort(intVector);

一切正常,但是如果我开始替换默认参数:

Sort::sort(intVector, std::less<int>(), merge);

我收到一条错误消息:Candidate template ignored: could not match 'function' against 'less'

更新:

我终于成功了 - 显式专门化函数调用似乎可以解决问题。另外,我没有为枚举值提供命名空间。

Sort::sort<int, std::vector<int>>(intVector, std::less<int>(), Sort::merge)

谢谢大家!

你的 std::function<bool(Elem, Elem)> comparator 应该是 std::function<bool(const Elem&, const Elem&)>std::function<bool(auto,auto)> 如果您使用的是 C++14。

 template <class Elem = int, class Container = std::vector<Elem>>
    void sort(std::shared_ptr<Container> vectorPointer,
              std::function<bool(Elem, Elem)> comparator = std::less<Elem>(),
              Type type = selection)

比较器类型取决于模板参数 Elem,因此当编译器执行模板推导规则时,它要求调用者提供的值具有与参数类型模式相匹配的类型。由于 'less' 和 'function' 不是同一类型,因此此函数不是有效匹配项。

(不要将类型推导逻辑与处理这些类型的实例时允许的转换顺序混淆。)

如果您将调用更改为看起来像这样它会起作用(尽管由于糟糕的用户体验,您显然不想这样做):

Sort::sort(shV, std::function<bool(int, int)>(std::less<int>()), Sort::merge);

这样,第二个参数的类型与模板所期望的相匹配。 上面的例子也解决了你对'merge'枚举器的使用,它在Sort命名空间中,需要命名空间限定。

可以对您的签名做一个小改动,将 Compare 作为另一个模板参数:

template <class Elem = int, class Container = std::vector<Elem>, 
          class Compare = std::less<Elem>>
void sort(std::shared_ptr<Container> vectorPointer,
      Compare comparator = Compare(),
      Type type = selection) {
    switch (type) {
        // ...
    }