如何使用lambda表达式作为模板参数?

时间:2010-09-28 07:24:37

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

如何使用lambda表达式作为模板参数?例如。作为初始化std :: set的比较类。

以下解决方案应该有效,因为lambda表达式只创建一个匿名结构,它应该适合作为模板参数。然而,产生了很多错误。

代码示例:

struct A {int x; int y;};
std::set <A, [](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    } > SetOfA;

错误输出(我正在使用g ++ 4.5.1编译器和--std = c ++ 0x编译标志):

error: ‘lhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
error: ‘rhs’ cannot appear in a constant-expression
error: ‘.’ cannot appear in a constant-expression
At global scope:
error: template argument 2 is invalid

这是GCC中的预期行为还是错误?

修改

有人指出,我正在使用lambda表达式,因为它们返回了他们所指的匿名结构的实例

但是,修复该错误并不能解决问题。我在以下代码中收到lambda-expression in unevaluated context错误:

struct A {int x; int y;};
typedef decltype ([](const A lhs, const A &rhs) ->bool {
    return lhs.x < rhs.x;
    }) Comp;
std::set <A, Comp > SetOfA;

4 个答案:

答案 0 :(得分:33)

std::set的第二个模板参数需要类型,而不是表达式,所以只是你错误地使用它。

您可以像这样创建一个集合:

auto comp = [](const A& lhs, const A& rhs) -> bool { return lhs.x < rhs.x; };
auto SetOfA = std::set <A, decltype(comp)> (comp);

答案 1 :(得分:4)

对于以这种方式使用的比较器,使用非0x方法仍然会更好:

struct A { int x; int y; };

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x;
  }
};

std::set<A, cmp_by_x> set_of_a;

但是,在0x中你可以使cmp_by_x成为本地类型(即在函数内定义它),这样更方便,当前的C ++禁止这样做。

此外,您的比较将A(x = 1,y = 1)和A(x = 1,y = 2)视为等效。如果不需要,您需要包含有助于唯一性的其他值:

struct cmp_by_x {
  bool operator()(A const &a, A const &b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y);
  }
};

答案 2 :(得分:1)

不确定这是否是您所要求的,但返回RetType并接受InType的lambda的签名将是:

std::function<RetType(InType)>

(确保#include <functional>

你可以通过使用typedef缩短它,但我不确定你是否可以使用decltype来避免弄清楚实际的类型(因为lambdas显然不能在那种情况下使用。)

所以你的typedef应该是:

typedef std::function<bool(const A &lhs, const A &rhs)> Comp

using Comp = std::function<bool(const A &lhs, const A &rhs)>;

答案 3 :(得分:0)

问题是最后一个模板参数是type不是对象,所以你可能想要做以下

    std::set <A, std::fuction<bool(const A &,const A &)>> 
              SetOfA([](const A lhs, const A &rhs) ->bool {
                                                             return lhs.x < rhs.x;
                                                          } > SetOfA;

为了简化您可以执行以下操作:

auto func = SetOfA([](const A lhs, const A &rhs) ->bool { return lhs.x < rhs.x;}
set <A,decltype(func)> SetOfA(func);

欢呼声