gpt4 book ai didi

c++ - Lambda 函数,奇怪的行为

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:22:58 25 4
gpt4 key购买 nike

假设我们在全局命名空间中声明了以下 lambda:

auto Less = [](int a,int b) -> bool
{
return a < b;
}

以及以下使用此 lambda 的代码:

template<typename T>
struct foo
{
foo(int v){}
bool operator<(const foo<T>&) const
{
return T(1,2);
}
};

int main()
{
typedef foo<decltype(Less)> be_less;
priority_queue<be_less> data;
}

如你所见,我使用 Less作为结构 foo 的模板参数.对于 g++4.9.2,此代码无法编译:

test1.cpp:13:21: error: no matching function for call to '<lambda(int, int)>::__lambda0(int, int)'
return T(1,2);
^
test1.cpp:13:21: note: candidates are:
test1.cpp:17:14: note: constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
auto Less = [](int a,int b) -> bool
^
test1.cpp:17:14: note: candidate expects 1 argument, 2 provided
test1.cpp:17:14: note: constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
test1.cpp:17:14: note: candidate expects 1 argument, 2 provided

但是我可能会通过添加两个小更改来解决这个问题,首先我需要将 lambda 更改为:

bool Less = [](int a,int b) -> bool
{
return a < b;
}

如你所见,我刚刚替换了 autobool ,仅此修改仍然不起作用:

test1.cpp:13:21: error: expression list treated as compound expression in functional cast [-fpermiss
ive]
return T(1,2);

除非我添加 -fpermissive ,或者我可以更改 operator< bool这样:

bool operator<(const foo<T>&) const
{
return T((1,2));
}

注意双括号。现在代码编译并且一切正常。

我的问题是,这就是 auto Less 的技术原因不工作但bool Less工作?

我相信我知道为什么在第二个 operator< 中需要双括号, 这应该是为了避免编译器解释 T(1,2)作为声明而不是调用。

谢谢你的时间

最佳答案

在您的第一个示例中,您正在构建 foo<T>其中 [T = decltype(Less)] .所以在这个表达式中

return T(1,2);

您正在尝试通过调用一个采用 2 int 的构造函数来构造 lambda 的实例。 s,这显然不存在。这正是错误消息告诉您的内容

error: no matching function for call to '<lambda(int, int)>::__lambda0(int, int)'

唯一存在的构造函数是 lambda 的复制和移动构造函数(从 lambda 表达式创建的闭包类型不是默认可构造的),编译器尝试匹配参数并失败

constexpr<lambda(int, int)>::<lambda>(const<lambda(int, int)>&)
constexpr<lambda(int, int)>::<lambda>(<lambda(int, int)>&&)
candidate expects 1 argument, 2 provided

在第二种情况下,通过进行此更改

bool Less = [](int a,int b) -> bool
{
return a < b;
};

您所做的是声明一个名为 Less 的 bool 变量并将其初始化为 true .

这是因为您拥有的 lambda 表达式是无捕获的,这意味着它可以隐式转换为指向函数的指针,该函数采用与 lambda 的 operator() 相同的参数。并返回与原始 lambda 相同的类型。因此,您将 lambda 表达式转换为 bool(*)(int,int) .

接下来,函数指针可以隐式转换为 bool并将始终评估为 true (假设它实际上指向一个函数的地址,它在这里就是这样做的)。所以Less被初始化为 true .

现在,decltype(Less)只不过是 bool .所以在这里您尝试将函数样式转换为 bool , 但传入 2 个参数

return T(1,2);

因此错误

error: expression list treated as compound expression in functional cast

通过添加额外的括号,您可以得到一个由逗号运算符分隔的 2 个子表达式组成的表达式。这将评估并丢弃第一个子表达式(1)并返回第二个(2)的值,然后将其转换为bool。 , 所以它转换为 true .


我不太确定您尝试做什么才能提出解决方案,但如果您想要的只是为 foo 定义一些比较谓词然后将由 priority_queue 调用,那么也许下面的作品?

struct foo
{
foo(int v) {}
};

auto Less = [](foo const& a, foo const& b) -> bool
{
return true; // do whatever comparison you need
};

int main()
{
using my_priority_queue = std::priority_queue<foo, std::vector<foo>, decltype(Less)>;

my_priority_queue data(Less); // pass a copy of the comparator
}

Live demo

关于c++ - Lambda 函数,奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28894062/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com