lambda捕获的const int变量的值类别

Value category of const int variable captured by lambda

本文关键字:变量 const lambda int      更新时间:2023-10-16

我一直在尝试了解何时以及何时不是lambda具有捕获默认的odr-uses在其周围范围中定义的具有自动存储持续时间的变量(此答案提示(。在探索这一点时,我遇到了一些好奇。GCC和Clang似乎在以下代码中对ID-Expression n的值类别表示不同意:

template <typename T> void assert_is_lvalue(const T&) {}
template <typename T> void assert_is_lvalue(const T&&) = delete;
int main() {
    const int n = 0;
    [=] { assert_is_lvalue(n); };
}

Clang成功编译了代码,而GCC则没有(error: use of deleted function(。哪一个是正确的?还是这是未指定或实现定义的东西?

将引用对象绑定到ODR-使用它,这可以通过删除Lambda的捕获默认默认状态,并观察到两个编译器然后抱怨n在没有捕获默认的情况的情况下无法隐式捕获。<</p>将lambda标记为mutable,对编译器的输出没有任何明显的影响。

事实证明,GCC的行为已从GCC-7.5向上变化!我使用以下代码来查看lambda中的n是如何捕获的,并且匹配了哪个模板。

#include <iostream>
#include <string>
#include <typeinfo>
#include <type_traits>
#include <memory>
#include <string>
#include <cstdlib>
template <class T>
constexpr std::string_view type_name()
{
    using namespace std;
    
    #ifdef __clang__
        string_view p = __PRETTY_FUNCTION__;
        return string_view(p.data() + 34, p.size() - 34 - 1);
    #elif defined(__GNUC__)
        string_view p = __PRETTY_FUNCTION__;
    
        #if __cplusplus < 201402
            return string_view(p.data() + 36, p.size() - 36 - 1);
        #else
            return string_view(p.data() + 49, p.find(';', 49) - 49);
        #endif
    #elif defined(_MSC_VER)
        string_view p = __FUNCSIG__;
        return string_view(p.data() + 84, p.size() - 84 - 7);
    #endif
}
template <typename T> 
void assert_is_lvalue(const T& param) 
{
    std::cout << "  T is " << type_name<T>() 
              << "  param is " << type_name<decltype(param)>() << 'n';
}
//template <typename T> void assert_is_lvalue(const T&&) = delete;
template <typename T> 
void assert_is_lvalue(const T&& param)
{
    std::cout << "  T is " << type_name<T>() 
              << "  param is " << type_name<decltype(param)>() << 'n';
}
int main() 
{
    const int n = 0;
    [=] { 
        std::cout << "  n is " << type_name<decltype(n)>() << 'n';
        assert_is_lvalue(n); 
    }();
    
    return 0;
}

这是结果:

GCC-7.5

n is const int
T is int  param is const int&&

GCC-8.1

n is const int
T is int  param is const int&

您可以在此处使用代码。