非模板类UartCommunication模板构造器实例化报错求助
我有一个非模板类UartCommunication,想给它添加一个模板构造函数,该构造函数需要接收模板类SafeQueue的对象,同时调用类内定义的另一个模板函数。
类的代码结构如下:
class UartCommunication { public: UartCommunication(const char *port, speed_t baudRate); template <typename SendStruct, typename ReceiveStruct, typename SendQueue = SafeQueue<SendStruct>, typename ReceiveQueue = SafeQueue<ReceiveStruct>> UartCommunication(const char* port, speed_t baudRate, SendQueue& sendQueue, ReceiveQueue& receiveQueue, int pollingTime, bool sendIfReceived) { port_ = port; baudRate_ = baudRate; serial_fd_ = open(port_, O_RDWR | O_NOCTTY | O_NDELAY); if (serial_fd_ == -1) { std::cerr << "Error opening serial port" << std::endl; // Handle error } std::cout << "serial_fd_:" << serial_fd_ << std::endl; ConfigureSerialPort(); // Start a thread to receive data receiveThread_ = std::thread(&SendAndReceiveStruct<SendStruct, ReceiveStruct>, this, sendQueue, receiveQueue, pollingTime, sendIfReceived); } // SentAndReceiveStruct from UART template <typename SendStruct, typename ReceiveStruct, typename SendQueue = SafeQueue<SendStruct>, typename ReceiveQueue = SafeQueue<ReceiveStruct>> void SendAndReceiveStruct(SendQueue& sendQueue, ReceiveQueue& receiveQueue, int pollingTime, bool sendIfReceived) { ///codes } }; // 线程安全队列模板类 template <class T> class SafeQueue { };
不使用模板构造函数创建UartCommunication对象时编译正常,但尝试以下方式创建对象时:
UartCommunication<InputStruct, OutputStruct> pcUart("/dev/ttyUSB0", B921600, AlgoTester::safeQueueInstanceAlgoInput, AlgoTester::safeQueueInstanceAlgoOutput, 20, false);
出现编译错误:
class "UartCommunication" may not have a template argument listC/C++(519)
‘UartCommunication’ is not a templateGCC error.
我需要传入SafeQueue的实例对象,无法直接将SafeQueue作为模板参数,希望解决该问题。
错误核心是**UartCommunication本身不是模板类,却被错误地添加了模板参数列表**。模板构造函数不需要在类实例化时显式指定模板参数,编译器会根据传入的实参自动推导。
具体修复步骤:
移除实例化时的模板参数列表
直接创建对象,编译器会根据传入的SafeQueue实例自动推导SendStruct和ReceiveStruct的类型:UartCommunication pcUart("/dev/ttyUSB0", B921600, AlgoTester::safeQueueInstanceAlgoInput, AlgoTester::safeQueueInstanceAlgoOutput, 20, false);修复线程调用模板函数的语法
原代码中std::thread调用模板成员函数的写法存在问题,需要正确指定模板参数,同时用std::ref传递队列引用(避免拷贝队列):// 正确写法:指定完整模板参数,用std::ref传递引用 receiveThread_ = std::thread(&UartCommunication::SendAndReceiveStruct<SendStruct, ReceiveStruct, SendQueue, ReceiveQueue>, this, std::ref(sendQueue), std::ref(receiveQueue), pollingTime, sendIfReceived);因为
std::thread会默认拷贝实参,若要传递队列的引用,必须用std::ref包装,否则原队列不会被修改。可选:显式指定模板参数(编译器推导失败时)
若编译器无法自动推导(复杂场景),可在C++17及以上版本中显式指定构造函数的模板参数:UartCommunication pcUart.template UartCommunication<InputStruct, OutputStruct>("/dev/ttyUSB0", B921600, AlgoTester::safeQueueInstanceAlgoInput, AlgoTester::safeQueueInstanceAlgoOutput, 20, false);
额外注意事项
- 确保
UartCommunication的成员变量(port_、baudRate_、serial_fd_、receiveThread_)已经在类中正确声明。 - 线程生命周期管理:需在类的析构函数中调用
receiveThread_.join()或detach(),避免程序退出时线程仍在运行。
内容的提问来源于stack exchange,提问作者BlueGreenRed

