在c ++中传递内联临时类需要为const如何解决这个问题

问题描述

我想用c ++ 11为不同的CPU(实际上是MCU)编写可移植代码。由于某些CPU不支持直接通过其内存地址空间读取程序数据(例如Atmel AVR),因此我需要一种解决方案,该解决方案可以使用直接地址或使用定制的Stream指针来调用函数以通过某些外部设备读取数据存储。

将此代码视为自定义库:

class IStream
{
    public: virtual char ReadChar();
};

class ConstMemoryStream : public IStream
{
    const char* Position;

    public: ConstMemoryStream(const char* startAddress)
    {
        Position = startAddress;
    }

    public: char ReadChar() override
    {
        return *Position++;
    }
};

void Send(char data) { } // Send data to serial port

现在,我想实现一个函数,该函数可以使用一个内存地址或一个Stream来读取以下数据:

// const parameter is needed here,otherwise error: invalid initialisation of non-const reference of type 'IStream&' from an rvalue of type 'IStream'
void PrintMessage(const IStream& stream)
{
    while (true) // TODO: end condition
        //Send(stream.ReadChar());  // this gives an error because i need to use a const parameter: passing 'const IStream' as 'this' argument discards qualifiers
        Send( ((IStream*)&stream)->ReadChar() );  // this works,this actually bypass the error above. IS THIS OK?????
}

void PrintMessage(char* address); // overload to use memory instead of stream. implementation not important here

接下来,我想用一个Stream调用PrintMessage,但是该流需要内联创建,并且在PrintMessage函数之外不再需要:

int main(void)
{
    // Requirement: ConstMemoryStream needs to be created and passed INLINE PrintMessage
    PrintMessage(ConstMemoryStream("Hello!")); // This works only if i put const in PrintMessage parameter.
}

上面的所有代码都可以编译和运行,但是我主要担心的是,我需要在PrintMessage函数中使用const参数(否则会出现错误)。因此,我需要进行一个丑陋的演员表:

Send( ((IStream*)&stream)->ReadChar() );

这基本上使参数成为非常量以避免错误。但是,有没有更好的解决方案来“合法地”做到这一点?

流实例本身不能为const,因为它在内部提高了位置,但是c ++需要将其作为const传递,因为它是一个内联临时变量,始终被视为右值。

在PrintMessage函数返回后,临时变量对其进行自我修改没有任何危害。

内联require我最后要做的是:

#ifdef CPU_AVR
    #define CSTR(str) ConstMemoryStream(PROGMEM str) // the PROGMEM attribute puts the text in a separate space not accessible in regular memory
#elif defined CPU_SAM
    #define CSTR(str) (char*)str
#endif

int main2(void)
{
    // If the CPU does not support direct address mapping to it's FLASH space,pass a stream instead of a direct memory pointer
    PrintMessage(CSTR("Hello"));
}

关于如何正确执行此操作而不丢弃该错误的任何想法?还是上面的当前代码可以接受?

解决方法

使用C ++ 11,您可以简单地将右值引用作为参数。

void PrintMessage(IStream && stream)
在这种情况下,

右值引用将绑定到临时对象,并且与左值引用几乎没有区别。

,

您的界面错误或使用错误。目前,您const_cast正在观看视频流。如果您传递了const IStream对象,那将是不确定的行为。

要么:

class IStream
{
    public: virtual char ReadChar() const;
};

或者:

void PrintMessage(IStream& stream)
{
    while (true) // TODO: end condition
        Send(stream.ReadChar());  
}

void PrintMessage(IStream&& stream)
{
    while (true) // TODO: end condition
        Send(stream.ReadChar());  
}

int main(void)
{
    PrintMessage(ConstMemoryStream("Hello!")); 
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...