导出类中使用std::queue触发MSVC编译错误求助
问题分析与解决:DLL导出类中使用std::queue导致的MSVC编译错误
问题描述
在DLL导出类SceneMgr中声明std::queue<BC*>成员变量时,MSVC编译器报出如下错误:
MSVC\14.40.33721\include\deque(874,31): error C2440: 'static_cast': cannot convert from 'std::_Deque_unchecked_iterator<std::_Deque_val<std::_Deque_simple_types<_Ty>>>' to 'unsigned __int64'
仅声明该对象未使用,且不导出SceneMgr类时编译正常。相关代码如下:
#define AILU_API __declspec(dllexport) #include <queue> template<typename T, size_t size_of_arr> constexpr uint32_t CountOf(T(&)[size_of_arr]) { return (uint32_t)size_of_arr; } template<typename T, size_t row, size_t col> constexpr uint32_t CountOf(T(&)[row][col]) { return (uint32_t)(row * col); } template<template<typename> typename TT, typename T> TT<T> operator-(const TT<T> v1, const TT<T> v2) { TT<T> res; for (uint32_t i = 0; i < CountOf(v1.data); i++) { res.data[i] = v1.data[i] - v2.data[i]; } return res; } class AILU_API BC { }; class AILU_API SceneMgr { public: private: inline static uint16_t s_scene_index = 0u; std::queue<BC*> _pending_delete_actors; };
错误原因
问题出在自定义的operator-模板上:
- 该模板要求
TT是单参数模板,但std::queue实际是双参数模板(第二个参数默认是std::deque<T>)。 - 导出
SceneMgr类时,编译器需要实例化std::queue<BC*>的相关成员,此时operator-模板会被错误匹配,尝试对std::queue调用不存在的公开成员data,进而触发内部迭代器转换的编译错误。 - 不导出类时,编译器可能因未进行完整实例化而未触发该错误。
解决方案
方案1:用C++20概念限制运算符适用范围(推荐)
添加概念约束,确保operator-仅作用于拥有数组类型data成员的自定义容器:
#include <concepts> template<template<typename> typename TT, typename T> requires requires(TT<T> v) { v.data; requires std::is_array_v<decltype(v.data)>; } TT<T> operator-(const TT<T> v1, const TT<T> v2) { TT<T> res; for (uint32_t i = 0; i < CountOf(v1.data); i++) { res.data[i] = v1.data[i] - v2.data[i]; } return res; }
方案2:用C++17及以下SFINAE限制匹配
通过std::void_t和std::enable_if判断类型是否符合要求:
#include <type_traits> template<template<typename> typename TT, typename T, typename = std::void_t<decltype(std::declval<TT<T>>().data)>> typename std::enable_if<std::is_array_v<decltype(std::declval<TT<T>>().data)>, TT<T>>::type operator-(const TT<T> v1, const TT<T> v2) { TT<T> res; for (uint32_t i = 0; i < CountOf(v1.data); i++) { res.data[i] = v1.data[i] - v2.data[i]; } return res; }
方案3:将运算符声明为自定义容器的友元
如果operator-仅针对特定自定义容器,直接在容器类内声明友元运算符,避免全局模板误匹配标准库容器。
修正后完整代码(C++20版本)
#define AILU_API __declspec(dllexport) #include <queue> #include <concepts> template<typename T, size_t size_of_arr> constexpr uint32_t CountOf(T(&)[size_of_arr]) { return (uint32_t)size_of_arr; } template<typename T, size_t row, size_t col> constexpr uint32_t CountOf(T(&)[row][col]) { return (uint32_t)(row * col); } template<template<typename> typename TT, typename T> requires requires(TT<T> v) { v.data; requires std::is_array_v<decltype(v.data)>; } TT<T> operator-(const TT<T> v1, const TT<T> v2) { TT<T> res; for (uint32_t i = 0; i < CountOf(v1.data); i++) { res.data[i] = v1.data[i] - v2.data[i]; } return res; } class AILU_API BC { }; class AILU_API SceneMgr { public: private: inline static uint16_t s_scene_index = 0u; std::queue<BC*> _pending_delete_actors; };
内容的提问来源于stack exchange,提问作者BoomBac
相关产品推荐
相关产品推荐

