Есть ли способ передать лямбда-выражение в качестве аргумента шаблона предиката? - PullRequest
0 голосов
/ 07 июня 2018

Есть ли способ заставить этот код компилироваться?Я хочу, чтобы моя функция сравнения была аргументом лямбда-шаблона.

#include <iostream>
#include <set>

int main() 
{
    std::set<int*, [](int *a, int *b){return *a<*b;}> S;
    return 0;
}

Я получаю следующие ошибки:

prog.cpp: In function ‘int main()’:
prog.cpp:6:17: error: lambda-expression in template-argument
  std::set<int*, [](int *a, int *b){return *a<*b;}> S;
                 ^
prog.cpp:6:51: error: template argument 2 is invalid
  std::set<int*, [](int *a, int *b){return *a<*b;}> S;

Может кто-нибудь помочь мне исправить код или объяснитьпочему это невозможно?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

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

#include <iostream>
#include <set>

template <typename ,typename>
struct swap_set_comparator{};

template <typename new_comp,typename set_type,typename comp,typename alloc>
struct swap_set_comparator<new_comp,std::set<set_type,comp,alloc> >
{
    using type = std::set<set_type,new_comp,alloc>;
};

template <typename container, typename... Args,typename Func>
auto make_set(Args&&... args,Func&& f)
{
   return typename swap_set_comparator<Func,container>::type(std::forward<Args>(args)...,std::forward<Func>(f));
}


int main() 
{
    // as already answered..

    auto comparator = [](int *a, int *b){return *a<*b;};
    std::set<int*,decltype(comparator)> S(comparator);

    // or 

    auto S2 = make_set<std::set<int*>>([](int *a, int *b){return *a<*b;});
    return 0;
}

Демо

0 голосов
/ 07 июня 2018

Ваш код недопустим, потому что:

[](int *a, int *b){return *a<*b;}

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

Вы можете сначала создать объект, а затем найти его тип, используя decltype:

auto comp = [](int *a, int *b){ return *a<*b; };
std::set<int*, decltype(comp)> S{comp};

Или в C ++ 20 вы можете напрямую применить decltype:

std::set<int*, decltype([](int *a, int *b){return *a<*b;})> S;

Поскольку ваша лямбда-код не требует захвата, другой способ - использовать тип указателя функции для типа компаратора и позволить компилятору преобразовать лямбда-указатель без захвата в указатель на функцию:

std::set<int*, bool (*)(int*, int*)> S([](int *a, int *b){ return *a<*b; });
...