可以将模板化的 lambda 存储到 std::function 中吗?
Possible to store templated lambda into std::function?
在 C++20 中,我们得到模板化的 lambda 来做这样的事情:
auto t = []<typename T>(T tmp){std::cout << tmp << std::endl;};
但是如果我需要通过 std::function<> 指定确切的类型怎么办? (不要依赖自动)。
是否可以将模板化的 lambda 存储到 std::function<>
包装器中?例如类似于以下内容?
template<typename T>
std::function<void(T)> t = []<typename T>(T tmp){std::cout << tmp << std::endl;};
并像常规模板函数一样使用它?
模板化 std::function
有问题。不是一个std::function
,而是多个。当您使用更多类型时,编译器将创建越来越多的全局数据。
此外,模板参数推导将不起作用,因为 std::function
变量是模板化的,而不是 std::function
的 operator()
。
此外,你不需要 C++20 也会有这个问题,用 C++14 试试这个:
// equivalent to the templated lambda, just different syntax
auto t = [](auto tmp){std::cout << tmp << std::endl;};
But what if I need to specify the exact type via std::function<>? (don't rely on auto).
问题是每个 lambda 都有一个无法写入的未命名的唯一类型。 auto
是 唯一 创建 lambda 类型变量的方法。
仅当您需要类型擦除,当您需要未知类型但已知接口的变量(如 operator()
)时,才使用 std::function
。 std::function
不是免费的 并且具有 运行时 和 二进制大小 成本。它是可调用类型的类型擦除包装器。
如果您真的需要 std::function
怎么办?
嗯,std::function
只能处理已知类型。例如,这将起作用:
std::function<void(int)> t = []<typename T>(T arg) { /* ... */ };
但只会调用 int
版本的 lambda。
要求 std::function
有一个模板 operator()
就像要求一个虚拟模板函数。无法实现。
如果您想使用名称已知的类型怎么办?
那就不要使用 lambda 表达式!它们可能不是您需要的工具!
这是不使用 auto 或 std::function
的等价物:
struct MyLambda {
template<typename T>
auto operator()(T arg) { /* ... */ }
};
MyLambda my_function_returning_lambda() {
// ...
}
// ...
MyLambda lambda = my_function_returning_lambda();
lambda(1);
lambda("works");
在 C++20 中,我们得到模板化的 lambda 来做这样的事情:
auto t = []<typename T>(T tmp){std::cout << tmp << std::endl;};
但是如果我需要通过 std::function<> 指定确切的类型怎么办? (不要依赖自动)。
是否可以将模板化的 lambda 存储到 std::function<>
包装器中?例如类似于以下内容?
template<typename T>
std::function<void(T)> t = []<typename T>(T tmp){std::cout << tmp << std::endl;};
并像常规模板函数一样使用它?
模板化 std::function
有问题。不是一个std::function
,而是多个。当您使用更多类型时,编译器将创建越来越多的全局数据。
此外,模板参数推导将不起作用,因为 std::function
变量是模板化的,而不是 std::function
的 operator()
。
此外,你不需要 C++20 也会有这个问题,用 C++14 试试这个:
// equivalent to the templated lambda, just different syntax
auto t = [](auto tmp){std::cout << tmp << std::endl;};
But what if I need to specify the exact type via std::function<>? (don't rely on auto).
问题是每个 lambda 都有一个无法写入的未命名的唯一类型。 auto
是 唯一 创建 lambda 类型变量的方法。
仅当您需要类型擦除,当您需要未知类型但已知接口的变量(如 operator()
)时,才使用 std::function
。 std::function
不是免费的 并且具有 运行时 和 二进制大小 成本。它是可调用类型的类型擦除包装器。
如果您真的需要 std::function
怎么办?
嗯,std::function
只能处理已知类型。例如,这将起作用:
std::function<void(int)> t = []<typename T>(T arg) { /* ... */ };
但只会调用 int
版本的 lambda。
要求 std::function
有一个模板 operator()
就像要求一个虚拟模板函数。无法实现。
如果您想使用名称已知的类型怎么办?
那就不要使用 lambda 表达式!它们可能不是您需要的工具!
这是不使用 auto 或 std::function
的等价物:
struct MyLambda {
template<typename T>
auto operator()(T arg) { /* ... */ }
};
MyLambda my_function_returning_lambda() {
// ...
}
// ...
MyLambda lambda = my_function_returning_lambda();
lambda(1);
lambda("works");