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

时间:2022-08-14 18:52:58

How to use lambda expression as a template parameter? E.g. as a comparison class initializing a std::set.

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

The following solution should work, as lambda expression merely creates an anonymous struct, which should be appropriate as a template parameter. However, a lot of errors are spawned.

下面的解决方案应该是有效的,因为lambda表达式仅仅创建了一个匿名结构,应该作为模板参数使用。但是,会产生很多错误。

Code example:

代码示例:

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

Error output (I am using g++ 4.5.1 compiler and --std=c++0x compilation flag):

错误输出(我使用的是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

Is that the expected behavior or a bug in GCC?

这是预期的行为还是GCC中的bug ?

EDIT

编辑

As someone pointed out, I'm using lambda expressions incorrectly as they return an instance of the anonymous struct they are referring to.

正如有人指出的,当lambda表达式返回它们所引用的匿名结构的实例时,我使用的是不正确的。

However, fixing that error does not solve the problem. I get lambda-expression in unevaluated context error for the following code:

然而,修正这个错误并不能解决问题。在未计算的上下文错误中,我得到如下代码的lambda表达式:

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 个解决方案

#1


33  

The 2nd template parameter of std::set expects a type, not an expression, so it is just you are using it wrongly.

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

You could create the set like this:

您可以创建这样的集合:

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

#2


4  

For comparators used this way, you're still better off with a non-0x approach:

对于使用这种方法的比较器,您最好使用非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;

However, in 0x you can make cmp_by_x a local type (i.e. define it inside a function) when that is more convenient, which is forbidden by current C++.

但是,在0x中,您可以将cmp_by_x设置为本地类型(即在函数中定义它),这样更方便,这是当前c++所禁止的。

Also, your comparison treats A(x=1, y=1) and A(x=1, y=2) as equivalent. If that's not desired, you need to include the other values that contribute to uniqueness:

同样,您的比较将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);
  }
};

#3


1  

Not sure if this is what you're asking, but the signature of a lambda which returns RetType and accepts InType will be:

不确定这是不是你想问的,但是返回RetType并接受InType的lambda的签名是:

std::function<RetType(InType)>

(Make sure to #include <functional>)

(确保#include <功能> )

You can shorten that by using a typedef, but I'm not sure you can use decltype to avoid figuring out the actual type (since lambdas apparently can't be used in that context.)

您可以使用typedef来缩短它,但是我不确定您是否可以使用decltype来避免计算出实际类型(因为显然不能在此上下文中使用lambdas)。

So your typedef should be:

所以你的定义应该是:

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

or

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

#4


0  

the problem is the last template parameter is type not an object, so you might want to do the following

问题是,最后一个模板参数的类型不是对象,所以您可能需要执行以下操作

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

to make it simpler you can do the following:

为了使它更简单,你可以做以下事情:

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

cheers

干杯

#1


33  

The 2nd template parameter of std::set expects a type, not an expression, so it is just you are using it wrongly.

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

You could create the set like this:

您可以创建这样的集合:

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

#2


4  

For comparators used this way, you're still better off with a non-0x approach:

对于使用这种方法的比较器,您最好使用非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;

However, in 0x you can make cmp_by_x a local type (i.e. define it inside a function) when that is more convenient, which is forbidden by current C++.

但是,在0x中,您可以将cmp_by_x设置为本地类型(即在函数中定义它),这样更方便,这是当前c++所禁止的。

Also, your comparison treats A(x=1, y=1) and A(x=1, y=2) as equivalent. If that's not desired, you need to include the other values that contribute to uniqueness:

同样,您的比较将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);
  }
};

#3


1  

Not sure if this is what you're asking, but the signature of a lambda which returns RetType and accepts InType will be:

不确定这是不是你想问的,但是返回RetType并接受InType的lambda的签名是:

std::function<RetType(InType)>

(Make sure to #include <functional>)

(确保#include <功能> )

You can shorten that by using a typedef, but I'm not sure you can use decltype to avoid figuring out the actual type (since lambdas apparently can't be used in that context.)

您可以使用typedef来缩短它,但是我不确定您是否可以使用decltype来避免计算出实际类型(因为显然不能在此上下文中使用lambdas)。

So your typedef should be:

所以你的定义应该是:

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

or

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

#4


0  

the problem is the last template parameter is type not an object, so you might want to do the following

问题是,最后一个模板参数的类型不是对象,所以您可能需要执行以下操作

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

to make it simpler you can do the following:

为了使它更简单,你可以做以下事情:

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

cheers

干杯