Сохраните аргументы snprintf для последующего использования - PullRequest
0 голосов
/ 03 мая 2018

Я хочу, чтобы мое приложение с графическим интерфейсом печатало динамические данные на экране (координаты мыши и т. Д.) В определенном пользователем формате и с использованием выбранных пользователем переменных. Мне нужно что-то вроде класса, который хранит этот формат (char*) и все его указатели переменных (int*, char*, std::string* и т. Д.)

Допустим, я хочу, чтобы всплывающая подсказка отображала координаты мыши. Мой класс будет:

class Printer{
private:
char *format;
// std::vector with pointers? Variadic template?

public:
   Printer(char *format, ...){
      // code
   }
};

Пользователь может определить формат с переменными:

int x, y;
Printer p("X (%d), Y (%d)", &x, &y);

Функция обратного вызова мыши обновляет значения x и y. И Printer сделает:

snprintf(buffer, sizeof(buffer), format, *variables);

После этого буфер содержит обновленные значения x и y, и его можно просто передать подсказке.

Как мне этого добиться?

1 Ответ

0 голосов
/ 03 мая 2018

Я не знаю, возможно ли это, с переменным списком аргументов, до C ++ 11.

Но, начиная с C ++ 11, используя шаблоны с переменными числами (для передачи списка аргументов с переменными числами в конструктор) и лямбда-функцию (где вы можете захватывать список ссылок на аргументы с переменным числом аргументов), вы можете написать что-то вроде

class Printer
 {
   private:
      char                              buffer[1024];
      std::string                       format;
      std::function<std::string(void)>  l;

   public:
      template <typename ... Args>
      Printer (char const * f0, Args & ... as) : format{f0}
       {
         l = [&] () -> std::string
          {
            snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]),
                     format.c_str(), as...);

            return buffer;
          };
       }

      std::string callback () const
       { return l(); }
 };

Вы можете использовать Printer следующим образом

int main ()
 {
   int x{10}, y{20};

   Printer p{"X (%d), Y (%d)", x, y};

   x = 100;
   y = 200;

   std::cout << p.callback() << std::endl; // print X (100), Y (200)
 }

Обратите внимание, что x и y передаются как ссылки, а не как указатели.

...