C ++ использует std :: great () в priority_queue и сортирует - PullRequest
4 голосов
/ 05 июля 2019

Почему документация для обоих случаев говорит об одном и том же, но они объявлены противоположным образом, один использует greater<int>, а другой - greater<int>(). Может ли кто-нибудь пролить свет на это?

Документация priority_queue cpp library говорит, что comp

может быть объектом сравнения, который будет использоваться для упорядочения кучи. Это может быть указатель функции или объект функции

priority_queue<int, vector<int>, greater<int>> minheap;  //works
priority_queue<int, vector<int>, greater<int>() > minheap; //why fail?

Документация библиотека cpp sort говорит то же самое, то есть comp может быть либо указателем на функцию, либо функциональным объектом.

sort (numbers.begin(), numbers.end(), std::greater<int>()); //works
sort (numbers.begin(), numbers.end(), std::greater<int>); //fail

Ответы [ 4 ]

4 голосов
/ 05 июля 2019

Третий аргумент шаблона для std::priority_queue - это тип компаратора.

С помощью greater<int>() вы создаете экземпляр (объект) класса greater<int> и передаете этот экземпляр (объект) в качестве аргумента вместо типа greater<int>.

Для std::sort третий аргумент функции - это реальный объект (или, скорее, все, что можно вызвать).


Что касается ссылки, на которую вы ссылаетесь, то это ссылка на конструктор , а не сам шаблон std::priority_queue. Аргументы конструктора похожи на аргументы функции и очень отличаются от аргументов шаблона.

3 голосов
/ 05 июля 2019

В этом объявлении

priority_queue<int, vector<int>, greater<int>> minheap; 

greater<int> - это аргумент шаблона, который определяет тип и соответствует параметру шаблона типа class Compare в priority_queue

template<class T, class Container = vector<T>,
class Compare = less<typename Container::value_type>>
class priority_queue;

В этомВ операторе

sort (numbers.begin(), numbers.end(), std::greater<int>());

используется конструктор по умолчанию для создания временного объекта типа greater<int>.

std::greater - это структура шаблона

template<class T = void> struct greater;

то есть его специализация предоставляет тип.

Вы можете использовать специализации шаблона в качестве спецификатора типа в объявлениях.Например,

std::greater<int> obj1;
std::greater<double> obj2;
std::greater<std::string> obj3;

В первом случае вы должны указать аргумент типа для соответствующего параметра шаблона типа.

Во втором случае вы должны указать объект типа greater<int>.

Учтите, что если вы попытаетесь использовать запись std::greater<int>() в качестве аргумента шаблона для priority_queue, то компилятор рассматривает ее как спецификатор типа функции, который имеет тип возвращаемого значения std::greater<int> и не имеетпараметры.Потому что компилятор ожидает спецификатор типа в качестве аргумента шаблона, а не выражения.Но указание такого типа функции в качестве аргумента шаблона типа не имеет смысла для priority_queue.

Чтобы сделать его более понятным, переписать вызов std :: sort следующим образом

std::greater<int> obj;
sort (numbers.begin(), numbers.end(), obj );

Как вы видите, std::greater<int> является спецификатором типа для переменной obj, которая передается в качестве аргумента функции std::sort.Разница между приведенным выше вызовом и этим вызовом

sort (numbers.begin(), numbers.end(), std::greater<int>());

заключается в том, что в последнем случае создается временный объект типа std::greater<int>, подобный std::greater<int>().

.демонстрационная программа

#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>

int main() 
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    std::greater<int> comp;

    //  Here is used an already created object of the type std::greater<int> 
    std::sort( std::begin( a ), std::end( a ), comp );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    //  Here is used a remporary object of the type std::less<int> 
    std::sort( std::begin( a ), std::end( a ), std::less<int>() );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    return 0;
}

Вывод программы

0 1 2 3 4 5 6 7 8 9 
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 
0 голосов
/ 05 июля 2019

Просто в зависимости от того, нужен ли вам тип (при определении типа) или значение (при вызове функции шаблона), вам нужен тип или созданный по умолчанию экземпляр типа соответственно.

Обратите внимание, что вы можете иметь противоположные эквивалентыиспользуя greater<int>{} greater<int>.Для sort компилятор выводит типы, и вы можете опустить вывод типов.В случае priority_queue вы можете использовать C ++ 17 и заставить компилятор выводить типы на основе аргументов конструктора.Итак, вот код, который выглядит странно, но он компилируется:

priority_queue a{ greater<int>{}, vector<int>{} };  

int tab[] { 3, 4, 5, 0 };
sort<int*, greater<int>>(tab, tab + 3, {});

https://wandbox.org/permlink/X4aHIzvOqAlOWGoP

0 голосов
/ 05 июля 2019

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

Аналогично, когда вынужно предоставить экземпляр, как для третьего аргумента функции сортировки, если вы предоставляете тип, вы получаете ошибку времени компиляции, и если вы предоставляете экземпляр по умолчанию, все в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...