【问题标题】:Lambda black magic taking different typesLambda黑魔法采取不同类型
【发布时间】:2020-11-15 17:03:03
【问题描述】:

试图找到另一种方法来简单地序列化我的代码,我有一个愚蠢的想法来尝试这个不可能的事情。但它奏效了。我真的很想知道为什么:

template <typename C>
void f(C c)
{
    int a = 1;
    float b = 1.5f;
    c(a);
    c(b);
}

int main()
{
    f([](auto v){
        std::cerr << v << "\n";
    });
    return 0;
}

我查看了生成的程序集 (g++-9.3 -O0 -g -S -fverbose-asm test.cpp -o test.s),似乎生成了两个不同的 lambda:一个采用浮点数,而另一个取整数。这是黑魔法吗?有没有人知道标准并且可以对此进行更多解释?

【问题讨论】:

    标签: c++ lambda auto


    【解决方案1】:

    通用 lambda 与

    struct lambda
    {
        template <typename T>
        auto operator()(T v) const
        {
            std::cerr << v << "\n";
        }
    // ...
    };
    

    lambda 本身不是模板,但它的成员 operator() 是。

    【讨论】:

    • 我确实喜欢将解释表述为语法重写,但由于 C++20 使 void f(auto) {...}auto f = []&lt;typename T&gt;(T) {...} 都有效,我发现这样做比较棘手:(跨度>
    • @cigien:我想说它允许更多的相似性,至于[]&lt;std::size_t ... Is&gt;(std::index_sequence&lt;Is...&gt;) {}。我会说 C++ 逻辑(冗长)需要第二种语法,简化为前者(因为它适用于具有概念语法的常规模板函数)。
    【解决方案2】:

    这个电话:

    f([](auto v){
            std::cerr << v << "\n";
        });
    

    将通用 lambda 作为参数 c 传递给 f。由于 auto 参数,通用 lambda 具有模板化成员 operator()

    所以当你拨打以下电话时:

    c(a);  // int argument
    c(b);  // float argument
    

    编译器将用int 实例化一个版本的lambda 成员operator(),用float 实例化一个版本的成员operator()

    【讨论】:

    • 好的,所以我们可以将 lambda 视为模板函数,在调用点实例化。有趣...而且功能强大。
    • @etham 差不多,除了答案中提到的,lambda 不是模板,但 operator() 成员是。
    猜你喜欢
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多