我知道lambda的类型是“隐藏的”和独特的。但是,“唯一”的确切含义是什么,在特殊情况下,相同的lambda代码会给出相同的类型吗?
(如果可能的话)我想使用这个“不变”来进行类型检查,如下所示:
#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++成功编译的,但只有标准的真相)
由于补语更符合最初的标题(很抱歉,由于我不得不离开办公室而来得有点晚),下面是一个更强的版本,用于而不是编译:
#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!
}发布于 2019-09-05 19:18:01
的确,标准并没有明确说明什么是“独特”,但我认为我们可以搞清楚。
首先,注意标准是“唯一的、未命名的非工会类类型”。形容词"unnamed“很强,足以暗示lambda闭包类型与使用struct或class关键字或由标准库定义的命名类不同(例如,lambda闭包类型不能是std::function<...>)。
那么,为什么标准会说“独一无二,没有名字”呢?它肯定告诉了我们关于两种不同的lambda闭包类型之间的比较。然而,在许多情况下,这将是多余的。如果我们有两个lambda表达式,比如:
auto f1 = [](int x) { return x; };
auto f2 = [](int x) { return 2*x; };显然,这两个lambda表达式不能具有相同的类型,因为它们的函数调用操作符有不同的行为。因此,关于每个闭包类型都是“唯一”的声明不会告诉我们关于f1和f2我们还不知道的任何事情。
然而,如果我们现在来看:
auto f3 = [](int x) { return x; };
auto f4 = [](int x) { return x; };在这里,“唯一”可以解释为f3和f4肯定有不同的类型,尽管lambda表达式具有相同的拼写和行为。
在这种情况下,这被普遍认为是“独特”的含义。如果标准并不意味着f3和f4有不同的类型,那么根本就没有理由使用“唯一”一词。相反,它只会说“未命名”,而不是“独特,未命名”。
于是问题就出现了,那就是唯一性在多大程度上扩展了。这可能意味着每个lambda表达式的计算结果都是不同的类型吗?不,这不可能是那个意思。这将使表达式的静态类型取决于它被执行了多少次(运行时属性),这是荒谬的。如果您的foo<int>的lambda每次执行foo<int>时都有不同的类型,那么会发生什么情况呢?这意味着foo<int>的签名在每次调用时都会改变。这不可能。foo<int>中的lambda必须始终具有相同的类型。
至于您的foo_1和foo_2情况,这里的两个lambda类型肯定是不同的。如果不是这样,“唯一”一词将是多余的。
发布于 2019-09-05 17:33:54
您所做的断言不是未定义的行为。闭包类型是impl定义的.在同一个编译器中比较lambda表达式类型之后,就没有问题了。
https://stackoverflow.com/questions/57810441
复制相似问题