【问题标题】:Creating a template inner lambda function?创建模板内部 lambda 函数?
【发布时间】:2020-01-16 13:46:54
【问题描述】:

我一直在尝试解决 C++ 中的下一个函数问题:

template <typename T>
auto createFunction(T& ClosuredData) {
    template <typename U>
    return [&](function<void(T&, U&)> Callback) {
        return [&](U& DataFromCallback) {
            Callback(ClosuredData, DataFromCallback);
        };
    };
};

// example use
struct Person {
   string name{"Foo"};
   int age = 20;
}
Person foo{};
auto mutate = createFunction(foo);
auto changeAge = mutate<int>([](Person& person, int& age) {
    person.age = age;
})

changeAge(20)

所以基本上是一个带有内部模板 lambda 的模板函数创建者。 但当然,据我所知,内部模板在 C++ 中是不可能的。 我尝试将回调设置为自动类型,但当然我无法推断出 DataFromCallback 导致错误的类型安全。

我能否在不引入类/结构的情况下以某种方式实现适当的类型安全?

编辑: 我看到的“解决方案”之一是使用自动类型而不是功能:

template <typename T>
auto CreateFunction(T& ClosuredData) {
    return [&](auto Callback) {
        return [&, Callback](auto DataFromCallback) {
            Callback(ClosuredData, DataFromCallback);
        };
    };
};

这确实很酷,但给人一种类型安全的错误感觉,例如:

{
    Person person{};
    auto personMutator = CreateFunction(person);
    auto changeAge = personMutator([](Person& person, int age) {
        person.age = age;
    });

    changeAge(""); // Would not throw an error in this line, but at an upper stack

    changeAge(any); // same stuff
}

【问题讨论】:

  • 即使你创建了这样一个 lambda(它可以使用新的 C++20 语法),mutate&lt;int&gt;(params) 也不起作用。您必须使用mutate.operator()&lt;int&gt;(params) 调用它,或者将参数转换为std::function
  • 为什么不引入结构/类名如此重要?这将使您的代码更具可读性,因为人们实际上可以追踪类型名称并弄清楚发生了什么。
  • 没那么重要,我只是想看看有没有可能。非常喜欢函数式编程。

标签: c++ templates lambda functional-programming


【解决方案1】:

您似乎可以使用自 C++14 以来可用的通用 lambda(基本上用作内部模板):

template <typename T>
auto CreateFunction(T& ClosuredData) {
    return [&](auto Callback) {
        return [&, Callback](auto DataFromCallback) {
            Callback(ClosuredData, DataFromCallback);
        };
    };
};

【讨论】:

  • 我实际上做了一些事情,但给人一种类型安全的错误感觉,因为我无法从回调中推断出 DataFromCallback :/。
  • @IstvanOrban “我无法从回调中推断出 DataFromCallback”是什么意思?
  • 所以基本上,如果我想创建类似的东西:(抱歉无法格式化下一行代码......){ Person person{}; auto personMutator = CreateFunction(person); auto changeAge = personMutator([](Person& person, int age) { person.age = age; });我的 changeAge 会接受任何参数。例如:changeAge("string") // 这行不会抛出任何错误,当然也不会编译 changeAge(123) // 同样的事情
  • 我猜你应该提供 mcve(带有在线编译器的链接)。 changeAge("string") 应该会导致编译时错误。
  • 是的,它会导致,但不会导致线路本身。所以调用 (changeAge(any)) 本身是完全有效的。错误将来自不同的堆栈。
猜你喜欢
  • 2020-07-22
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-11
  • 2019-01-20
  • 2019-08-02
  • 1970-01-01
相关资源
最近更新 更多