我想foo::func()
在 lambda 表达式中访问,但此时foo
已声明该类但未定义该类。有什么办法可以懒惰地进行 lambda 表达式吗?
如果我用等效的函数对象替换 lambda 表达式,那么我可以做到这一点。
这是等效的代码:
单独的声明和定义方法
struct foo; // forward declaration
struct lambda {
void operator()(foo& f); // `lambda` only has declaration of `operator()`.
};
struct bar {
void memfun(foo& f) {
// Call `lambda` function object with the reference of incomplete `foo`.
lambda()(f);
}
};
struct foo { // Define foo
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
// Define `lambda::operator()` after definition of `foo`.
inline void lambda::operator()(foo& f) {
f.func();
}
int main() {
foo f;
bar b;
b.memfun(f);
}
运行演示:https ://wandbox.org/permlink/12xV6655DZXZxLqF
它可以在 g++ 和 clang++ 上编译。
我的目标是 Lambda 表达式方法
我试图消除struct lambda
。
这是代码:
struct foo; // forward declaration
struct bar {
void memfun(foo& f) {
// Write explicit return type seems to instanciate
// lambda body lazily on g++
[](auto& f) -> void {
f.func();
}(f);
}
};
struct foo { // definition
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main() {
foo f;
bar b;
b.memfun(f);
}
关键是显式地编写返回类型void
。如果我省略了这一点,那么 g++ 和 clang++ 的编译器都会在f.func();
. 如果我添加void
返回类型,似乎 g++ 会懒惰地实例化 lambda 表达式的主体。但是 clang++ 仍然输出相同的错误。
结果:
- 在 g++ 9.2.0 上成功
- clang++ 9.0.0 上的错误
哪个编译器有效?
如果 clang++ 是有效的,有没有办法像等效的一样懒惰地实例化 lambda 表达式的主体struct lambda
?
具有成员函数模板方法的函数对象
我注意到分离声明和定义方法并不真正等同于Lambda 表达式方法。lambda 表达式auto&
的参数是lambda::operation()
,但分离声明和定义方法的参数是foo&
。
应该是模板。这是等效的代码:
struct foo; // forward declaration
struct lambda {
template <typename T>
void operator()(T& f) {
f.func();
}
};
struct bar {
void memfun(foo& f) {
lambda()(f);
}
};
struct foo { // definition
void func() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main() {
foo f;
bar b;
b.memfun(f);
}
运行演示:https ://wandbox.org/permlink/dJ1tqQE8dIMNZqgY
它不需要单独声明lambda::operator()
. 并在 g++ 和 clang++ 上懒惰地实例化它。如果可能的话,我正在寻找一种使用 lambda 表达式的方法。
背景(我为什么需要这个?)
我正在使用基于元编程的状态机库 Boost (Candidate) SML。
见 https://github.com/boost-experimental/sml/issues/93#issuecomment-283630876
struct with_prop
对应于struct foo
。struct table
对应于struct bar
。- 外部 lambda 表达式
[](with_prop& p) {...
对应于void bar::memfun(foo& f)
.- 由于 SML 重载解析,参数
foo& f
不能是auto& f
.
- 由于 SML 重载解析,参数
- 内部 lambda 表达式
[](auto& p) -> void { ...
对应于[](auto& f) -> void { ...
auto table::operator()() const noexcept
不能分开声明和定义,因为 SML 在operator()()
定义之前使用返回类型。