2013-05-08 2 views
8

В моем приложении у меня много журналов. Я накапливаю все ошибки из всех журналов в одном месте по имени errorsLogger. Я реализовал это следующим образом:как перенаправить переменное количество аргументов в другую функцию?

static Logger errorsLogger; 

.... 

void Logger::Error(std::string format, ...) { 
    va_list arglist; 
    va_start(arglist, format); 

    if (this != &errorsLogger) { 
     errorsLogger.Error(format, arglist);  // how to forward parameters? 
    } 

    vfprintf(logFile, , format.c_str(), arglist); 
    fprintf(logFile, "\n"); 

    fflush(logFile); 
    va_end(arglist); 
} 

Однако этот код не работает, как ожидалось errorsLogger содержит немного странные строки - кажется, переменная аргументы не был принят. Как исправить мой код?

+1

Вам нужна версия 'Error', который принимает [' va_list'] (http://en.cppreference.com/w/cpp/utility/variadic/va_list). – BoBTFish

+1

Рассмотрите возможность изменения интерфейса вашего регистратора, чтобы он выглядел как 'ostream', вы сможете делать такие вещи, как:' Logger :: error() << "переменная x есть" << x; 'Фактически' Logger :: error() 'может возвращать' ostream & ' – piokuc

+0

Могу ли я просто форматировать строку как первый шаг, а затем просто переместить std :: string? – javapowered

ответ

13

Типичная формулировка этого в C, чтобы иметь две функции, одна из которых принимает ... и тот, который принимает va_list (например, по сравнению с printfvprintf). В C++ это удобно делать это с перегрузкой:

// public 
void Logger::Error(const std::string& format, ...) { 
    va_list args; 
    va_start(args, format); 
    Error(format, args); 
    va_end(args); 
} 

// private 
void Logger::Error(const std::string& format, va_list args) { 
    if (this != &errorsLogger) 
     errorsLogger.Error(format, args); 

    vfprintf(logFile, format.c_str(), args); 
    fprintf(logFile, "\n"); 
    fflush(logFile); 
} 

Использование C++ 11, можно сделать непосредственно с VARIADIC шаблоном. Вы также можете перенаправить аргументы в вариативные функции C-стиля.

template<class... Args> 
void Logger::Error(const std::string& format, Args&&... args) {  
    if (this != &errorsLogger) 
     errorsLogger.Error(format, std::forward<Args>(args)...); 

    fprintf(logFile, format.c_str(), std::forward<Args>(args)...); 
    fprintf(logFile, "\n"); 
    fflush(logFile); 
} 
+0

Вы можете определенно использовать вариативные шаблоны для пересылки функций C Variadic. [Живой пример] (http://melpon.org/wandbox/permlink/0fbi8R2PCrOJkeFv) –

4

Одним словом, вы не можете.

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

+0

Почему вы это делаете? – 2013-05-08 18:52:37

+1

Возможно, кто-то хотел, чтобы это было короче? Или они органический химик, предпочитающий писать OC (OH)? Трудно сказать, действительно. –

+0

@CodyGray LOL, хороший момент об органических химиков. – 2013-05-08 19:39:04

0

Для того, чтобы работать, Logger::Error должен быть объявлено, чтобы принять va_list в качестве параметра, так же, как vfprintf, а не переменные аргументов в виде ... как fprintf.

Смежные вопросы