Функция и внутренняя функция одинаковые аргументы - PullRequest
0 голосов
/ 08 января 2019

Может ли кто-нибудь помочь мне, как добиться, чтобы моя функция принимала только те типы аргументов, которые функция может вызывать внутри нее?

У меня есть класс Logger, который можно запустить с объектом HardwareSerial в функции setup() кода Arduino.
Затем в loop() я бы хотел вызвать функцию Logger.print(), которая должна принимать только те аргументы, которые можно назвать HardwareSerial.print().

Вот мои уродливые и не работающие попытки:

template <typename... ARGS>
size_t print(const ARGS &... args) {
    if (serial != NULL) {
        if (sizeof...(args) == 2) {
            return this->serial->print(args[0], args[1]);
        } else if (sizeof...(args) == 1) {
            return this->serial->print(args[0]);
        }
    }
    return 0;
}

template <typename T>
size_t print(const T &t, typename std::enable_if<std::is_convertible<const __FlashStringHelper *, T>::value ||
                                                     std::is_base_of<const String &, T>::value ||
                                                     std::is_array<T>::value ||
                                                     //std::is_same<char[std::extent<T>::value], T>::value ||
                                                     std::is_same<char, T>::value ||
                                                     std::is_same<char *, T>::value ||
                                                     std::is_same<const char *, T>::value ||
                                                     std::is_same<unsigned char, T>::value ||
                                                     std::is_same<int, T>::value ||
                                                     std::is_same<unsigned int, T>::value ||
                                                     std::is_same<long, T>::value ||
                                                     std::is_same<unsigned long, T>::value ||
                                                     std::is_same<double, T>::value ||
                                                     std::is_convertible<const Printable &, T>::value ||
                                                     std::is_convertible<struct tm *, T>::value,
                                                 T>::type * = 0) {
    if (serial != NULL) {
        return this->serial->print(t);
    }
    retrun 0;
}

Ответы [ 3 ]

0 голосов
/ 08 января 2019

Синтаксис затрат на шаблон вариации равен

template <typename... ARGS>
size_t print(const ARGS&... args) {
    if (serial != nullptr) {
        return this->serial->print(args...);
    }
    return 0;
}

, чтобы сделать его SFINAE дружественным, вы можете использовать:

template <typename... ARGS>
auto print(const ARGS&... args) -> decltype(this->serial->print(args...))
{
    if (serial != nullptr) {
        return this->serial->print(args...);
    }
    return 0;
}
0 голосов
/ 08 января 2019

Поскольку вам нужен тот же интерфейс, что и HardwareSerial, со всеми методами print, println и write, ваш класс Logger должен наследоваться от Print, а затем реализовывать только метод write(uint8_t) это только звонки HardwareSerial с write(uint8_t).

class Logger : public Print {
    public:
        virtual size_t write(uint8_t);
}
size_t Logger::write(uint8_t c) {
    if (this->serial != NULL) {
       return this->serial->write(c);
    }
    return 0;
}

Подробнее о Print классе: https://playground.arduino.cc/Code/Printclass

0 голосов
/ 08 января 2019

Определение возможности вызова функции - это просто, когда вы используете decltype для проверки SFINAE:

template <typename... ARGS>
auto print(const ARGS &... args) -> decltype(this->serial->print(args...)) {
    if (serial != NULL) {
        return this->serial->print(args...);
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...