首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数模板中定义的lambda闭包类型可以说是什么?

函数模板中定义的lambda闭包类型可以说是什么?
EN

Stack Overflow用户
提问于 2019-09-05 17:30:33
回答 2查看 145关注 0票数 3

我知道lambda的类型是“隐藏的”和独特的。但是,“唯一”的确切含义是什么,在特殊情况下,相同的lambda代码会给出相同的类型吗?

(如果可能的话)我想使用这个“不变”来进行类型检查,如下所示:

代码语言:javascript
复制
#include <type_traits>

template <typename T>
auto foo(const T y)
{
  return [=](T x) { return x * y; }; 
}

int main()
{
  auto f1 = foo<int>(4.);
  auto f2 = foo<int>(6.); // fails with auto f2 = foo<double>(6.);

  static_assert(std::is_same_v<decltype(f1), 
                               decltype(f2)>); // is this ok or undefined behavior?
}

在此之前,我想确定c++标准说的话:它是可以的还是未定义的行为?

(这段代码是由g++和clang++成功编译的,但只有标准的真相)

由于补语更符合最初的标题(很抱歉,由于我不得不离开办公室而来得有点晚),下面是一个更强的版本,用于而不是编译:

代码语言:javascript
复制
#include <type_traits>

template <typename T>
auto foo_1(const T y)
{
  return [=](T x) { return x * y; };
}

template <typename T>
auto foo_2(const T y)
{
  return [=](T x) { return x * y; };
}

int main()
{
  auto f1 = foo_1<int>(4.);
  auto f2 = foo_2<int>(6.);

  static_assert(std::is_same_v<decltype(f1), decltype(f2)>); // fails!
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-05 19:18:01

的确,标准并没有明确说明什么是“独特”,但我认为我们可以搞清楚。

首先,注意标准是“唯一的、未命名的非工会类类型”。形容词"unnamed“很强,足以暗示lambda闭包类型与使用structclass关键字或由标准库定义的命名类不同(例如,lambda闭包类型不能是std::function<...>)。

那么,为什么标准会说“独一无二,没有名字”呢?它肯定告诉了我们关于两种不同的lambda闭包类型之间的比较。然而,在许多情况下,这将是多余的。如果我们有两个lambda表达式,比如:

代码语言:javascript
复制
auto f1 = [](int x) { return x; };
auto f2 = [](int x) { return 2*x; };

显然,这两个lambda表达式不能具有相同的类型,因为它们的函数调用操作符有不同的行为。因此,关于每个闭包类型都是“唯一”的声明不会告诉我们关于f1f2我们还不知道的任何事情。

然而,如果我们现在来看:

代码语言:javascript
复制
auto f3 = [](int x) { return x; };
auto f4 = [](int x) { return x; };

在这里,“唯一”可以解释为f3f4肯定有不同的类型,尽管lambda表达式具有相同的拼写和行为。

在这种情况下,这被普遍认为是“独特”的含义。如果标准并不意味着f3f4有不同的类型,那么根本就没有理由使用“唯一”一词。相反,它只会说“未命名”,而不是“独特,未命名”。

于是问题就出现了,那就是唯一性在多大程度上扩展了。这可能意味着每个lambda表达式的计算结果都是不同的类型吗?不,这不可能是那个意思。这将使表达式的静态类型取决于它被执行了多少次(运行时属性),这是荒谬的。如果您的foo<int>的lambda每次执行foo<int>时都有不同的类型,那么会发生什么情况呢?这意味着foo<int>的签名在每次调用时都会改变。这不可能。foo<int>中的lambda必须始终具有相同的类型。

至于您的foo_1foo_2情况,这里的两个lambda类型肯定是不同的。如果不是这样,“唯一”一词将是多余的。

票数 6
EN

Stack Overflow用户

发布于 2019-09-05 17:33:54

您所做的断言不是未定义的行为。闭包类型是impl定义的.在同一个编译器中比较lambda表达式类型之后,就没有问题了。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57810441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档