Ошибка компилятора с пользовательской функцией компаратора в качестве аргумента шаблона

#c #compiler-errors

#c #ошибки компилятора

Вопрос:

Я не могу заставить класс Heap принять компаратор в качестве второго аргумента шаблона. Компилятор продолжает пытаться создать экземпляр объекта Comparator. Почему? Все, что я хочу, это сравнение между двумя предоставленными входными данными. Вот ошибка компилятора:

   In file included from main.cpp:1:0:
Heap.hpp: In instantiation of ‘void Heap<T, Cmp>::bubbleUp(size_t) [with T = long unsigned int; Cmp = Comparator<long unsigned int>; size_t = long unsigned int]’:
Heap.hpp:29:35:   required from ‘void Heap<T, Cmp>::insert(const Tamp;) [with T = long unsigned int; Cmp = Comparator<long unsigned int>]’
main.cpp:7:15:   required from here
Heap.hpp:119:9: error: no matching function for call to ‘Comparator<long unsigned int>::Comparator(__gnu_cxx::__alloc_traits<std::allocator<long unsigned int> >::value_typeamp;, __gnu_cxx::__alloc_traits<std::allocator<long unsigned int> >::value_typeamp;)’
         if (Cmp(fArray[idx], fArray[getParent(idx)]))
         ^
Heap.hpp:119:9: note: candidates are:
Heap.hpp:128:7: note: constexpr Comparator<long unsigned int>::Comparator()
 class Comparator
  

Вот класс

 #pragma once
#include <vector>
#include <functional>
#include <assert.h>
#include "boost/optional.hpp"

template <typename T, typename Cmp>
class Heap
{

  public:
    Heap()
        : fArray()
    {
    }
    ~Heap() {}
    void insert(const T amp;toInsert)
    {
        fArray.push_back(toInsert);
        bubbleUp(fArray.size() - 1);
    }


  private:
    std::vector<T> fArray;
    size_t getParent(size_t i) const
    {
        assert(i / 2 < fArray.size());
        return i / 2;
    } 


    void bubbleUp(size_t idx)
    {
        if (idx == 0)
        {
            return;
            // return early if root
        }
        // If heap property violated, swap and recurse upwards
        if (Cmp(fArray[idx], fArray[getParent(idx)])
        {
            std::iter_swap(fArray.begin()   idx, fArray.begin()   getParent(idx));
            bubbleUp(getParent(idx));
        }
    }
};
  

Вот компаратор:

 template <typename T>
class Comparator
{
  public:
    bool operator()(const T amp;o1, const T amp;amp;o2)
    {
        return o1 < o2;
    }
};
  

Вот основная функция

 int main(){
    Heap< size_t,Comparator<size_t> >  h;
    h.insert(4);
    h.insert(5);
    h.insert(6);
    h.insert(3);
}
  

Ответ №1:

Здесь вы вызываете свой компаратор:

 if (Cmp(fArray[idx], fArray[getParent(idx)])
  

Cmp это ваш класс компаратора. Это параметр шаблона, который вы указываете в качестве вашего Comparator экземпляра шаблона.

Теперь отложим на время тему шаблонов. Для всех практических целей Cmp здесь есть класс. Представьте, что это обычный класс:

 class Cmp {

 // ...
};
  

Теперь спросите себя, что бы выражало:

 Cmp(fArray[idx], fArray[getParent(idx)])
  

значит, тогда?

Это, конечно, означает: создайте временный экземпляр Cmp класса и передайте два параметра в Cmp конструктор.

Теперь вы должны быть в состоянии понять вашу проблему. В вашем классе comparator нет конструктора, который принимает два параметра. Это то, что говорит вам ваш компилятор.

Вместо этого в вашем классе comparator используется перегруженный () оператор.

В вашем случае использования нет смысла создавать временный объект. Ваше очевидное намерение здесь — смоделировать ваш Heap шаблон и использовать его аналогично тому, как контейнеры стандартной библиотеки C используют классы компаратора.

На самом деле контейнеры стандартной библиотеки C , грубо говоря, объявляют член класса, который является экземпляром класса comparator, а затем вызывают () перегрузку оператора члена класса.

Это свободно переводится в ваш Heap шаблон, объявляющий частный член класса:

 private:
    Cmp cmp;
  

И затем вызывающий () перегрузку оператора этого члена класса.

 if (cmp(fArray[idx], fArray[getParent(idx)])
  

Также обратите внимание, что стандартные библиотечные контейнеры C обычно имеют перегруженный конструктор, который принимает явный экземпляр класса comparator, а затем использует его для копирования-конструирования своего частного экземпляра comparator.