如何解决模板成员函数存入std::function数组/元组的编译错误?
修复模板成员函数存入std::array/std::tuple的编译错误
以下针对两种存储场景的编译错误,分别说明原因并给出修复方案:
一、std::arraystd::function场景的错误修复
错误原因
编译器无法直接将模板成员函数f<I>转换为std::function<unsigned int()>,核心问题有两点:
- 成员函数必须依赖对象的
this指针才能调用,直接传递函数名无法绑定当前对象; - 即便
enable_if限制了重载,编译器仍无法自动推导函数类型以消除歧义。
修复方案
可以通过两种方式明确绑定当前对象并消除类型歧义:
方式1:使用lambda捕获this
#include <array> #include <functional> #include <type_traits> #include <utility> template <bool X> struct A { template <unsigned int I, bool activate = X, class = std::enable_if_t<activate>> unsigned int f() { return 0; } template <unsigned int... I> auto collect_allf_impl(std::integer_sequence<unsigned int, I...>) { return std::array<std::function<unsigned int()>, 3>{ [this](){ return this->f<I>(); }... }; } auto collect_allf() { return collect_allf_impl(std::make_integer_sequence<unsigned int, 3>{}); } }; int main() { A<true> x{}; auto all = x.collect_allf(); }
方式2:使用std::bind绑定当前对象
#include <array> #include <functional> #include <type_traits> #include <utility> template <bool X> struct A { template <unsigned int I, bool activate = X, class = std::enable_if_t<activate>> unsigned int f() { return 0; } template <unsigned int... I> auto collect_allf_impl(std::integer_sequence<unsigned int, I...>) { return std::array<std::function<unsigned int()>, 3>{ std::bind(&A::f<I>, this)... }; } auto collect_allf() { return collect_allf_impl(std::make_integer_sequence<unsigned int, 3>{}); } }; int main() { A<true> x{}; auto all = x.collect_allf(); }
二、std::tuple场景的错误修复
错误原因
直接写f<I>时,编译器无法将其解析为明确的成员函数指针类型——即便enable_if限制了重载,仍需要显式指定包含类类型的成员函数地址。
修复方案
显式取成员函数的地址,明确指定为&A<X>::f<I>:
#include <array> #include <functional> #include <type_traits> #include <tuple> #include <utility> template <bool X> struct A { template <unsigned int I, bool activate = X, class = std::enable_if_t<activate>> unsigned int f() { return 0; } template <unsigned int... I> auto collect_allf_impl(std::integer_sequence<unsigned int, I...>) { return std::make_tuple(&A<X>::f<I>...); } auto collect_allf() { return collect_allf_impl(std::make_integer_sequence<unsigned int, 3>{}); } }; int main() { A<true> x{}; auto all = x.collect_allf(); }
如果需要存储可直接调用的对象而非成员函数指针,也可以用lambda捕获this存入tuple:
#include <array> #include <functional> #include <type_traits> #include <tuple> #include <utility> template <bool X> struct A { template <unsigned int I, bool activate = X, class = std::enable_if_t<activate>> unsigned int f() { return 0; } template <unsigned int... I> auto collect_allf_impl(std::integer_sequence<unsigned int, I...>) { return std::make_tuple([this](){ return this->f<I>(); }...); } auto collect_allf() { return collect_allf_impl(std::make_integer_sequence<unsigned int, 3>{}); } }; int main() { A<true> x{}; auto all = x.collect_allf(); }
内容的提问来源于stack exchange,提问作者francesco
相关产品推荐
相关产品推荐

