【问题标题】:Pass C++20 Templated Lambda to Function Then Call it将 C++20 模板化 Lambda 传递给函数,然后调用它
【发布时间】:2021-05-12 15:03:23
【问题描述】:

我正在尝试将模板化的 lambda 传递给函数,然后使用模板参数调用它,以启用该函数的自定义类型的特化。

但是当我尝试调用 lambda 时,我得到了这个错误:error: invalid operands to binary expression

对于任何想玩这个的人来说,这里有一个神螺栓链接:https://gcc.godbolt.org/z/qYPcea

#include <cstdint>
#include <string>
#include <cstring>

enum class Alignment : uint8_t {
    
    one,
    two,
    four,
    eight
};

template <Alignment alignment, typename T>
static void align(T& pointer)
{
    intptr_t& value = reinterpret_cast<intptr_t&>(pointer);
    value += (-value) & ((uint64_t)alignment - 1);
}

template<typename Lambda, typename T>
static void specialization(Lambda&& lambda, const T& t) 
{
   lambda<Alignment::eight>(t.data(), t.size());
}

int main()
{
    uint8_t buffer[1024];

    void *writeTo = buffer;

    auto lambda = [&] <Alignment alignment> (const void *input, uint32_t inputSize) -> void
    {
        align<alignment>(writeTo);
        writeTo = memcpy(writeTo, buffer, inputSize);
    };
    
    std::string input("helloworld");

    specialization(lambda, input);

    return 0;
}

【问题讨论】:

    标签: c++ templates lambda c++20


    【解决方案1】:

    问题在于 lambda 不是类模板,它们只是成员调用运算符(即 operator())被模板化的常规类。

    当为泛型 lambda 推导模板参数时,这种区别并不明显(这是一件非常好的事情)。

    因此,在您的示例中,lambda 不是类模板,但您使用的语法将用于类,而不是成员函数。

    如果您想显式指定 lambda 的模板参数,您需要说明您正在调用 lambda 的成员 operator(),并且您需要说明它是用于消除歧义的模板.

    lambda.template operator()<Alignment::eight>(t.data(), t.size());
    

    这是compiles 的代码版本。

    【讨论】:

      【解决方案2】:

      我听说你对 lambdas 有疑问,孩子。

      您是否考虑过使用...更多的 lambdas 来修复它?

      template<auto k>
      constexpr std::integral_constant<std::decay_t<decltype(k)>, k> constant = {};
      
      auto TemplateInvoke = [](auto&& f) {
        return [&](auto...constants) {
          return [&](auto&&...args)->decltype(auto) {
            return f.operator()<decltype(constants)::value...>(decltype(args)(args)...);
          };
        };
      };
      

      there we go.

      template<typename Lambda, typename T>
      static void specialization(Lambda&& lambda, const T& t) 
      {
        TemplateInvoke(lambda)(constant<Alignment::eight>)(t.data(), t.size());
      }
      

      所有与 lambdas 相关的问题都可以通过更多 lambdas 来解决。

      问题是lambda&lt;template args&gt;(stuff) 不起作用;你需要lambda.operator()&lt;template args&gt;(stuff)。这种语法很尴尬。

      上述尝试通过有效地创建一种不同的 C++ 方言来减少尴尬,您可以将模板参数作为函数参数传递。

      有些人可能会认为这是矫枉过正。

      他们可能是那种认为“一个返回 lambda 的 lambda 又返回一个 lambda 并将一个 lambda 作为参数的 lambda”由于语法含糊不清的原因而令人困惑的人。

      【讨论】:

      • 次要的一点,第一句中的“kid”并不总是翻译得很好,可以看作是一种光顾。你可能想避免它。
      • 啊哈,这就是 lambda 演算
      猜你喜欢
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 2021-06-22
      • 2017-03-24
      相关资源
      最近更新 更多