有没有办法将lambda表达式作为谓词模板参数传递?

时间:2018-06-07 15:12:46

标签: c++ c++11 templates lambda c++14

有没有办法让这段代码编译?我希望将我的比较函数作为lambda模板参数。

#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 :(得分:10)

您的代码无效,因为:

[](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;

由于lambda是无捕获的,另一种方法是使用比较器类型的函数指针类型,让编译器将无捕获的lambda转换为函数指针:

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

答案 1 :(得分:1)

现在回答,但如果您想要写,这是另一种选择 您的比较器内联而不指定类型..

#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;
}

Demo