Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编译器如何区别于常规函数处理lambda?_C++_Lambda_Compilation_Language Lawyer - Fatal编程技术网

C++ 编译器如何区别于常规函数处理lambda?

C++ 编译器如何区别于常规函数处理lambda?,c++,lambda,compilation,language-lawyer,C++,Lambda,Compilation,Language Lawyer,我想知道编译器是如何对待lambda函数而不是常规函数的。即使排除捕获列表,我认为它的名称,它的行为似乎略有不同 例如,正如我在上一篇文章中所使用的,我使用了一个constexpr lambda并将其作为常规函数参数传递。我引用了部分答案 constexpr函数的参数本身不是constexpr对象,因此不能在常量表达式中使用它们 在本例中,lambda基本上是值的包装器 编辑:全局功能 foo([](){ return 4; }); // C++17 Lambda's are implicitl

我想知道编译器是如何对待lambda函数而不是常规函数的。即使排除捕获列表,我认为它的名称,它的行为似乎略有不同

例如,正如我在上一篇文章中所使用的,我使用了一个constexpr lambda并将其作为常规函数参数传递。我引用了部分答案

constexpr函数的参数本身不是constexpr对象,因此不能在常量表达式中使用它们

在本例中,lambda基本上是值的包装器

编辑:全局功能

foo([](){ return 4; }); // C++17 Lambda's are implicitly constexpr
无论何时传递全局函数,编译器都会抱怨(与使用lambda相反),该函数无论是否定义为constexpr,都不能在常量条件下使用:

prog.cc:8:20: error: 'l' is not a constant expression

从你的代码片段中删除一些无关的东西,我们得到

template<typename T>
constexpr void foo(T t)
{
    constexpr int i = t();
}

constexpr int f() { return 42; }
auto l = []{ return 42; }
T
被推断为调用
foo(L)
中与
L
等价的类型

  • T
    在调用
    foo(f)
    中被推断为
    int(*)(

  • 在这两种情况下,
    t
    不是
    foo
    中的constexpr


  • 表达式
    e
    是一个核心常量表达式,除非按照抽象机器的规则对
    e
    的求值将求值以下表达式之一:[……]

    • 左值到右值的转换,除非[…]

      • 非易失性glvalue,指的是使用constexpr定义的非易失性对象,或指的是此类对象的不可变子对象,或

      • 一种文本类型的非易失性glvalue值,指的是一个非易失性对象,其生存期开始于
        e
        的计算范围内

    通过
    int(*)(
    调用需要左值到右值的转换
    t
    不是用
    constexpr
    定义的对象,也不是在
    t()
    的计算中开始其生命周期的。因此
    t()
    不是
    foo(f)
    中的
    constepr

    调用
    操作符()
    不需要左值到右值的转换。由于没有成员访问权限,因此它只是一个
    constexpr
    函数调用。因此
    t()
    foo(l)
    中的
    constepr


    从核心常量表达式到常量表达式有不同的定义,但在这里的讨论中并不重要。

    您可以展示lambda实现吗?如果您传递任何由常量表达式初始化的函子,它将编译。如果将
    l()
    替换为
    fptr()
    ,其中
    fptr
    是由常量表达式初始化的函数指针,则它也将编译。我看到的唯一区别是,当使用函数参数调用时,应用于参数以初始化参数的函数到指针转换可能不会被假定为常量表达式。但我怀疑在c++20中,它应该被假定为一个恒定的初始化,而在c++17中,它甚至更加模糊。@Oliv Oops,我只是觉得你在我写答案时已经说过同样的话。
    template<typename T>
    constexpr void foo(T t)
    {
        constexpr int i = t();
    }
    
    constexpr int f() { return 42; }
    auto l = []{ return 42; }
    
    struct L { constexpr int operator()() const { return 42; } };