You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非模板类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本身不是模板类,却被错误地添加了模板参数列表**。模板构造函数不需要在类实例化时显式指定模板参数,编译器会根据传入的实参自动推导。

具体修复步骤:

  1. 移除实例化时的模板参数列表
    直接创建对象,编译器会根据传入的SafeQueue实例自动推导SendStruct和ReceiveStruct的类型:

    UartCommunication pcUart("/dev/ttyUSB0", B921600, AlgoTester::safeQueueInstanceAlgoInput, AlgoTester::safeQueueInstanceAlgoOutput, 20, false);
    
  2. 修复线程调用模板函数的语法
    原代码中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包装,否则原队列不会被修改。

  3. 可选:显式指定模板参数(编译器推导失败时)
    若编译器无法自动推导(复杂场景),可在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:14:57