неявные преобразования в / из std :: array и простую структуру - PullRequest
0 голосов
/ 12 мая 2019

Я использую C API для связи с устройством через SPI.Все команды приводят к 3-байтовому регистру с устройства.Поскольку std :: array хорош и совместим с C API, я написал небольшую оболочку, которая отправляет команду и возвращает 3-байтовый массив.

Регистр "STATUS" более сложный, и поэтому я создал структурув нем только один 3-байтовый массив std ::.Основная цель - дать возможность простым const-методам обрабатывать все смещения, маскирование, CRC и т. Д., Которые нужны регистру.

        using devReg = std::array<uint8_t, 3>;

        struct Status {
            // default to all null
            explicit Status() : raw{0} {}
            // construct from std::array
            explicit Status(const devReg& a) : raw(a) {}
            // assign to and from std::array
            Status& operator=(const devReg& a) { raw = a; return *this; }
            // convert to std::array
            explicit operator devReg&() { return raw; }
            explicit operator const devReg&() const { return raw; }

            devReg raw; // raw data

            /// Indicates the FIFO watermark has been hit
            constexpr bool eint() const { return raw[0]&0x80U; }
            /*** Many other simple functions to handle the spare bitfields and validate data ***/

        };

        devReg cmdRead(const RegAddress cmd)
        {
            std::array<uint8_t, 3> buf = {0};
            SPIShim::select();
            // send write command: shift reg address right once and set bit 0
            SPIShim::write(static_cast<uint8_t>(cmd));
            SPIShim::read(buf.data(), buf.size());
            SPIShim::deSelect();
            return buf;
        }

        bool cmdWrite(const RegAddress cmd, const std::array<uint8_t, 3>& r)
        {
            SPIShim::select();
            // send read command: shift reg address left once and clear bit 0
            SPIShim::write(static_cast<uint8_t>(cmd));
            const size_t count = SPIShim::write(r.data(), r.size());
            SPIShim::deSelect();
            return count == 3;
        }

        // Works
        Status getStatus1() {
            Status s(cmdRead(RegAddress::STATUS));
            return s;
        }

        // Works
        Status getStatus2() {
            Status s;
            s = cmdRead(RegAddress::STATUS);
            return s;
        }

        // Works
        Status getStatus3() {
            return static_cast<Status>(cmdRead(RegAddress::STATUS));
        }

        // error: conversion from 'devReg' to non-scalar type 'Status' requested
        Status getStatus4() {
            Status s = cmdRead(RegAddress::STATUS);
            return s;
        }

        // error: could not convert 'cmdRead(1) from 'devReg to 'Status'
        Status getStatus5() {
            return cmdRead(RegAddress::STATUS);
        }

        // error: no known conversion for argument 2 from 'Status' to 'const devReg&'
        bool setStatus(const Status& s) {
            cmdWrite(RegAddress::STATUS, s);
        }

Я вроде понимаю, почему getStatus4() не работает, я думаю, std:: массив будет нуждаться в перегрузке оператора в качестве члена, который я не могу добавить.Но я не очень понимаю, почему getStatus5() не работает.И похоже, что перегрузка explicit operator const devReg&() должна заставить setStatus() работать!

В чем здесь проблема?В конце я хотел бы создать простые структуры, которые содержат один базовый std :: array и несколько функций, но в показанных случаях он работает взаимозаменяемо с эквивалентным std :: array.

Примечание: Простой обходной путь - возврат с использованием статического приведения и передача в функцию массива с помощью s.raw.Так что на самом деле я ищу лучшего понимания здесь и, если это возможно, немного более приятный код.

...