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

发布于 2024-09-25 04:37:28 字数 1038 浏览 5 评论 0原文

如何使用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;

How to use lambda expression as a template parameter? E.g. as a comparison class initializing a 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.

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):

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?

EDIT

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

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

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷心人i 2024-10-02 04:37:28

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

您可以像这样创建该集合:

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

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

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);
花落人断肠 2024-10-02 04:37:28

对于以这种方式使用的比较器,您仍然最好使用非 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);
  }
};

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

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++.

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:

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);
  }
};
柳絮泡泡 2024-10-02 04:37:28

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

std::function<RetType(InType)>

确保 #include

您可以通过使用来缩短它typedef,但我不确定您是否可以使用 decltype 来避免弄清楚实际类型(因为 lambda 显然不能在该上下文中使用。)

所以您的 typedef 应该是:

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

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

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

std::function<RetType(InType)>

(Make sure to #include <functional>)

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.)

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)>;
魂归处 2024-10-02 04:37:28

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

    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);

干杯

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文