Неизвестный обратный вызов метода класса, который принимает 0 аргументов и возвращает тип, преобразуемый в int

0

Я делаю интерфейс протокола. Этот протокол должен быть сервером для отправки данных АЦП с устройства. Различные микроконтроллеры имеют библиотеки, которые позволяют читать АЦП, но, разумеется, они разные.

Например, аналоговое чтение в Nucleo:

AnalogIn ain(A0); 
unsigned short value = ain.read_u16();

И Ардуино:

int analogPin = 3;
int val = analogRead(analogPin);

Хотя эти методы возвращают разные типы и на самом деле совершенно разные типы, они возвращают одни и те же данные.

Мой вопрос заключается в том, можно ли сделать класс, который принимает обе эти функции в качестве обратного вызова и возвращает их возвращаемое значение как int.

Как это:

class ThisIsNotReal {
  public:
    ThisIsNotReal(<ANY TYPE THAT CAN CONVERT TO INT HERE> (*cb)() ) {
      callback = cb;
    }
    int getVal() {
       return callback();
    }

  private:
    <ANY TYPE ... (some super magical template? anyone?)> (*cb)()

}

Конечно, моя цель - иметь совместимый с Arduino код без написания слишком большого кода. Кроме того, я хочу изучить магию шаблонов.

  • 1
    Рассматривали ли вы int val = static_cast<int>(ain.read_u16()); ?
Теги:
callback
templates

3 ответа

1

Если у вас нет компилятора С++ 11 для всех целевых устройств с использованием обратного вызова, это не обязательно будет просто. Это связано с различиями между требованиями к хранению и аргументами, необходимыми для вызова различных функций. Потому что если вы можете подумать о создании общего интерфейса для чтения ввода с порта ввода-вывода, а затем предоставить уникальную реализацию для каждого целевого устройства/платформы. Это позволит вам иметь общий метод инициализации объекта, связанного с IO, а также чтение из порта ввода-вывода.

Даже если у вас есть компилятор С++ 11 для ваших целевых платформ, использование std::function или virtual функций может быть нежелательным (или даже вариантом), если они окажут влияние на производительность. Что-то вроде следующего кода может быть более жизнеспособным, так как это просто.

#if defined (IS_NUCLEO)
struct InputDevice
{
    InputDevice(int port) : device(port) {}

    int read() const
    {
        return static_cast<int>(device.read_u16());
    }

    AnalogIn    device;
};
#endif

#if defined(IS_ARDUINO)
struct InputDevice
{
    InputDevice(int port) : port(port) {}

    int read() const { return analogRead(port); }

    int port;
};
#endif

Я предлагаю вам адаптировать его для удовлетворения ваших точных требований.

1

кажется, что std::function и lambda могут помочь, например:

AnalogIn ain(A0); 
std::function<int()> AdcRead = [ain](){ return ain.read_u16(); };

А также

const int analogPin = 3;
std::function<int()> AdcRead = [analogPin](){ return analogRead(analogPin); };
  • 0
    Нет тега C ++ 11, хотя.
  • 3
    @Pradhan: Теперь, если не указано C ++ 98 / C ++ 03, я предполагаю, что C ++ 11 / C ++ 14.
Показать ещё 1 комментарий
0

ThisIsNotReal должен хранить указатель типа ConvertFuncToIntBase* conv и вызывать conv->getVal(). Вы создадите соответствующий экземпляр, вызвав makeIntConverter в конструкторе ThisIsNotReal. makeIntConverter не будет компилироваться, если возвращаемый тип переданной ему функции не конвертируется в int. Хотя нижеприведенное решение с использованием std::enable_if и std::is_convertible, для которого требуется С++ 11, вы можете использовать аналогичные методы Boost для С++ 03.

class ConvertFuncToIntBase
{
public:
virtual int getVal() = 0;
virtual ~ConvertFuncToIntBase(){}
};

template <typename T>
class ConvertFuncToInt : ConvertFuncToIntBase
{
public:
ConvertFuncToIntLand(T (*cb)()) : callback(cb)
{
}

int getVal()
{
 return (int)callback();
}

private:
T (*callback)();
};

template <typename T, typename = typename std::enable_if<std::is_convertible<T, int>>::type>
std::unique_ptr<ConvertFuncToIntBase> makeIntConverter(T (*cb)())
{
 return std::unique_ptr<ConvertFuncToIntBase>(new ConvertFuncToInt<T>(cb));
}
  • 1
    Некоторые опечатки : callback не определен, ConvertFuncToInt наследует (конфиденциально) от самого себя, ConvertFuncToIntLand не является конструктором, нет виртуального деструктора для базового класса, отсутствует указатель для makeIntConverter (тогда как unique_ptr будет лучше).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню