编译报错:std::function模板隐式实例化未定义,求技术协助
解决类成员函数存储到std::unordered_map的编译错误
核心错误分析
- std::function类型定义错误:原代码中
std::unordered_map<int,std::function<void(*)(args...)>>写法错误,std::function的模板参数应为函数签名void(args...),而非void(*)(args...)(这是函数指针的签名)。std::bind返回的可调用对象签名是void(args...),和原定义的function类型不匹配,直接导致编译失败。 - 单例实例不匹配:main函数中调用
TestClassA<TestClassB>::instance().Remove(1)时,模板参数只传入TestClassB,但Add操作使用的是TestClassA<TestClassB,int,int>,这是两个完全独立的模板实例,它们的单例对象互不关联,Remove操作无法作用到之前Add的map上。 - 内存泄漏风险:
testCBIns用new创建后未释放,建议用智能指针管理生命周期。
修改后的完整代码
#include <QApplication> #include <unordered_map> #include <memory> #include <QDebug> #include <functional> template<typename T,typename ...args> class TestClassA { public: static TestClassA& instance() { static TestClassA a; return a; } void Add(int a,T* b,void(T::*)(args...)); void Remove(int a); // 修正std::function的类型为正确的函数签名 std::unordered_map<int,std::function<void(args...)>> m_test{}; }; template<typename T, typename ...args> void TestClassA<T,args...>::Add(int a, T *b, void (T::*pf)(args...)) { // 绑定成员函数时,需显式声明占位符,匹配成员函数的参数数量 this->m_test.emplace(a, std::bind(pf, b, std::placeholders::_1, std::placeholders::_2...)); } template<typename T, typename ...args> void TestClassA<T,args...>::Remove(int a) { this->m_test.erase(a); } class TestClassB { public: void TestTwo(int,int) { qDebug()<<"TestTwo"; }; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); // 使用智能指针管理对象,避免内存泄漏 std::unique_ptr<TestClassB> testCBIns = std::make_unique<TestClassB>(); // 统一使用相同的模板实例,保证Add和Remove操作作用于同一个map auto& testAIns = TestClassA<TestClassB,int,int>::instance(); testAIns.Add(1, testCBIns.get(), &TestClassB::TestTwo); testAIns.Remove(1); MainWindow w; w.show(); return a.exec(); }
补充说明
- 使用
std::bind绑定带参数的成员函数时,必须用std::placeholders::_1、std::placeholders::_2等占位符预留参数位置,否则生成的可调用对象无法接收后续传入的参数。 - 模板的不同实例是完全独立的,单例模式也不例外,因此必须保证所有操作都针对同一个模板实例。
内容的提问来源于stack exchange,提问作者Savner_Dig
相关产品推荐
相关产品推荐

