使用推导式this的函数无法绑定到std::bind_front的问题求助
使用deducing-this的函数无法传入std::bind_front的问题分析
问题背景
尝试用deducing-this替代CRTP以减少模板代码,却遇到了无法将使用deducing-this的成员函数传入std::bind_front的编译错误。在Boost.Beast中常用bind_front_handler传递回调,但Connection类的回调改用deducing-this后无法正常绑定,测试环境为Clang 18.1.0。
示例代码
#include <iostream> #include <functional> struct A { void foo_deducing_this(this auto& self, int x) { self.bar(x); } }; template <typename Deriv> struct B { void foo_crtp(int x) { static_cast<Deriv *>(this)->bar(x); } }; struct C : A, B<C> { void bar(int x) { std::cout << "number is " << x << "\n"; } }; void test(const std::function<void(int)>& f, int x) { f(x); } int main() { C c; c.foo_deducing_this(1); c.foo_crtp(2); c.bar(3); // 编译失败 // test(std::bind_front(&C::foo_deducing_this, c), 5); test(std::bind_front(&C::foo_crtp, c), 6); test(std::bind_front(&C::bar, c), 7); }
Boost.Beast回调场景示例
stream.async_read(buffer, beast::bind_front_handler(&Connection::on_read, this->shared_from_this()));
问题原因
deducing-this语法定义的成员函数本质是模板函数:this auto& self会被编译器解析为模板参数,而非固定的对象类型。当尝试直接取&C::foo_deducing_this的地址时,编译器无法自动推断模板参数(即self的具体类型),而std::bind_front和beast::bind_front_handler都需要明确的、已实例化的函数类型,而非未解析的模板。
对比CRTP版本的foo_crtp:当B<C>实例化后,foo_crtp是一个具体的非模板成员函数,不存在参数推断问题,因此可以直接取地址传递。
解决方案
1. 显式指定模板参数
直接为deducing-this函数指定模板实参,让编译器实例化出具体的函数版本:
test(std::bind_front(&C::foo_deducing_this<C&>, c), 5);
在Boost.Beast场景中:
stream.async_read(buffer, beast::bind_front_handler( &Connection::on_read<Connection&>, this->shared_from_this()));
2. 使用Lambda表达式包裹(推荐)
Lambda会自动推导调用时的类型,无需手动指定模板参数,写法更简洁:
test([&c](int x) { c.foo_deducing_this(x); }, 5);
在Boost.Beast场景中,结合shared_from_this使用:
stream.async_read(buffer, [self = shared_from_this()](auto&&... args) { self->on_read(std::forward<decltype(args)>(args)...); });
内容的提问来源于stack exchange,提问作者Keltek
相关产品推荐
相关产品推荐

