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

Okt*_*ist 8 c++ lambda language-lawyer c++17 value-categories

我一直在试图理解何时何时不具有捕获默认odr的lambda-使用在其周围范围内定义的自动存储持续时间的变量(由此答案提示).在探索周围时,我偶然发现了一点点好奇心.GCC和Clang似乎不同意n以下代码中id-expression的值类别:

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); };
}
Run Code Online (Sandbox Code Playgroud)

Clang成功编译代码,而GCC不编译(error: use of deleted function).哪一个是正确的?或者这是未指定或实现定义的东西?

绑定对象的引用应该使用它,并且通过删除lambda的capture-default并观察两个编译器然后抱怨在n没有捕获默认值的情况下不能隐式捕获来确认.

将lambda标记为mutable编译器的输出没有明显的差别.

Ali*_*Ali 2

事实证明,从 gcc-7.5 开始,gcc 的行为已经发生了变化!我使用以下代码来查看如何在 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;
}
Run Code Online (Sandbox Code Playgroud)

结果如下:

海湾合作委员会-7.5

n is const int
T is int  param is const int&&
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会-8.1

n is const int
T is int  param is const int&
Run Code Online (Sandbox Code Playgroud)

你可以在这里使用代码。