我有一个关于lambda表达式的相等比较的问题。我尝试阅读了一些相关资料,但却没有找到关于这个的任何内容。
[] (Args ...args) -> ReturnType { ... };
对于这种没有闭包的lambda表达式,因为它们有空的捕获列表,所以
==
和 !=
运算符的工作方式与静态函数相同(好吧,似乎编译器也生成它们作为静态函数)。但对于带有闭包的任何比较尝试都会导致编译错误。以下是一个简单的程序示例:
#include <typeinfo>
#include <iostream>
struct WrapperBase {
virtual ~WrapperBase() = default;
virtual bool operator==(WrapperBase& v) = 0;
virtual bool operator!=(WrapperBase& v) = 0;
};
template<typename _Tp>
struct Wrapper : WrapperBase {
Wrapper(const _Tp& v) : value(v) { }
bool operator==(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value == vv.value;
}
catch(std::bad_cast& err) { }
return false;
}
bool operator!=(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value != vv.value;
}
catch(std::bad_cast& err) { }
return true;
}
//
_Tp value;
};
template<typename _Tp>
WrapperBase* create_wrapper(const _Tp& v) {
return new Wrapper<_Tp>(v);
}
struct Base {
Base(int a, int b) : wrapper(nullptr), a(a), b(b) { }
virtual ~Base() { delete wrapper; }
virtual WrapperBase* create_wrapper() = 0;
WrapperBase* wrapper;
int a;
int b;
};
struct ClassA : Base {
ClassA(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [] (int v1, int v2) { return v1 + v2; };
return ::create_wrapper(lambda);
}
};
struct ClassB : Base {
ClassB(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [=] (int v1, int v2) { return a + b + v1 + v2; };
return ::create_wrapper(lambda);
}
};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
// all works fine:
ClassA a1(1, 2);
ClassA a2(3, 4);
std::cout << (*a1.wrapper == *a1.wrapper) << std::endl; // true
std::cout << (*a2.wrapper == *a2.wrapper) << std::endl; // true
std::cout << (*a1.wrapper == *a2.wrapper) << std::endl; // true
// cause compilation error:
ClassB b1(1, 2);
ClassB b2(3, 4);
std::cout << (*b1.wrapper == *b1.wrapper) << std::endl;
std::cout << (*b2.wrapper == *b2.wrapper) << std::endl;
std::cout << (*b1.wrapper == *b2.wrapper) << std::endl;
return 0;
}
比较在ClassA实例中创建的lambda表达式总是返回
true
,即使它们在不同的上下文中创建(正如我所说)。另一方面,ClassB甚至无法编译,因为其lambda的运算符==
和!=
未找到。看起来,这个程序不太规范,以我尝试的方式比较lambda会导致程序的行为未定义。但如果确实是未定义的行为,它们怎么能被比较呢?(我猜,根本不能)
operator==
。 - Columbo