C ++: Как я могу создать функцию, которая принимает объединенные строки в качестве параметра? - PullRequest
0 голосов
/ 09 июня 2018

Могу ли я спроектировать мою функцию регистрации таким образом, чтобы она принимала объединенные строки следующей формы, используя C ++?

int i = 1;
customLoggFunction("My Integer i = " << i << ".");

.

customLoggFunction( [...] ){
    [...]
    std::cout << "Debug Message: " << myLoggMessage << std::endl << std::endl
}

Редактировать:

Использование std :: string в качестве атрибута функции работает для объединенной строки, но затем переданная неконкатенированная строка, такая как customLoggFunction ("example string"), выдает ошибку времени компиляции, сообщающуюфункция не применима для char [].Когда я перегружаю функцию следующим образом ...

customLoggFunction(std::string message){...}
customLoggFunction(char message[]){...}

... конкатенированные строки начинают работать.

Я загрузил код: http://coliru.stacked -crooked.com / а / d64dc90add3e59ed

Ответы [ 4 ]

0 голосов
/ 10 июня 2018

Одним из подходов является простой служебный класс, который использует стандартный поток в шаблонной функции-члене:

class LogStream {
    public:
        template <class T> LogStream& operator << (const T& rhs) {
            stream << rhs;
            return *this;
        }

    private:
        std::stringstream stream;
};

Член потока, выполняющий всю работу, затем используется в деструкторе,

~LogStream() {
    std::cout << stream.str() << std::endl;
}

и вы можете создавать временные объекты для передачи ваших аргументов для конкатенации:

LogStream() << "anything with std::ostream operator: " << 1.2345 << ' ' << std::hex << 12;

Дополнительное состояние (например, уровень журнала) можно передать конструктору, часто сопровождаемому вспомогательными функциями, такими как LogStream debug() { return LogStream(...); },Однако, когда вы достигнете определенного уровня сложности, вы, возможно, захотите переключиться на библиотеку журналов.

0 голосов
/ 09 июня 2018

Для тривиальных проектов это одна из немногих вещей, для которых я использую MACRO.Вы можете сделать что-то вроде этого:

#define LOG(m) do{ std::cout << timestamp() << ": " << m << '\n'; }while(0)

// ...

LOG("error: [" << errno "] " << filename << " does not exist.");

Обычно MACROS следует избегать , но нет другого способа получить именно это с помощью стандартной функции.Итак ...

Примечание: Пустое условие do{...}while(0) позволяет вам разместить MACRO в местах, которые MACRO обычно не могут пройти, если он содержит несколько операторов.

0 голосов
/ 10 июня 2018

Вы можете сделать это, определив новый оператор <<.Из расплывчатой ​​памяти реализация функций с этими тремя сигнатурами сделает свое дело: </p>

std::string operator<<(const char * a, const std::string & b);
std::string operator<<(const std::string & a, const char * b);
std::string operator<<(const std::string & a, const std::string & b);

Каждый из них должен объединить свои аргументы и вернуть std :: string.

Как бы то ни было, он чувствуетнеправильно.Идет против зерна C ++.Я предлагаю более простое решение на C ++, а именно - преобразовать ваш регистратор в класс и написать члены оператора << () для этого класса, чтобы вы могли запустить </p>

customLog << "My Integer i = " << i << "." << "\n";
0 голосов
/ 09 июня 2018

Невозможно сделать с тем же синтаксисом, о котором вы просили, если вы не прибегаете к макросам.

Но если вы не возражаете заменить << на ,, тогда вы можете сделать следующее:

#include <iostream>
#include <string>
#include <sstream>

void log_impl(const std::string &str)
{
    std::cout << str;
}

template <typename ...P> void log(const P &... params)
{
    std::stringstream stream;

    (stream << ... << params);
    // If you don't have C++17, use following instead of the above line:
    // using dummy_array = int[];
    // dummy_array{(void(stream << params), 0)..., 0};

    log_impl(stream.str());
}

int main()
{
    log("1", 2, '3'); // prints 123
}
...