草庐IT

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

coder 2024-02-15 原文

假设我们在全局命名空间中声明了以下 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/

有关c++ - Lambda 函数,奇怪的行为的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  3. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  9. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  10. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

随机推荐