Как мы все знаем, если по какой-то причине вы printf()
что-то, а не поток (это редко, но иногда может случиться), вам нужно указать соответствующий спецификатор формата (d
для подписанного int, u
для неподписанных и т. д. и т. д.). Теперь, так как printf()
является частью стандартной библиотеки C ++, а не просто наследием C, я надеюсь, что что-то будет
template <typename T>
const std::string format_specifier;
Что позволит, скажем:
template <typename Foo>
void bar(const Foo& my_foo) {
printf(format_specifier<Foo>, my_foo);
}
Стандартная библиотека содержит что-то подобное?
Заметки:
std::cout
Конечно, это то, что вы должны сделать по умолчанию. Я спросил о функции, которая является частью стандартной библиотеки; если бы он был удален из него, вы могли бы сказать: «это никогда не должно использоваться, поэтому ваш вопрос не имеет значения».Первоначально я написал это как комментарий, так как это казалось слишком коротким.
Краткий ответ — «нет», так как стандарт C ++ не определяет никаких таких возможностей.
Заданы свойства функций, которые унаследованы от стандартной библиотеки C по причинам обратной совместимости (без перегрузки, допускается как в глобальном пространстве имен, так и в пространстве имен std и т. Д.), А также способ использования C ++. iostream
занятия поощряются, я был бы удивлен, если бы такая функция когда-либо стала стандартизированной.
Он не существует в библиотеке C ++ по некоторым причинам.
Во-первых, если вы хотите, чтобы C ++ помог вам найти правильный способ вывода объекта, C ++ предлагает вам инжекторы для stream
классы. Поток выбирает подходящий конвертер и может быть изменен с помощью манипуляторов — его даже можно проинструктировать, как распечатать произвольный объект путем перегрузки ostream& operator << (ostream&, const T&)
,
Но с другой стороны, строка формата printf может использоваться на других языках (Python, Java), и для старых программистов, которые ее использовали, гораздо проще использовать, чем манипуляторы io. Но его можно использовать в довольно сложных строках, смешивающих константные метки и переменные разных типов:
printf("Operation %-*s : %10.2f$ %2d%/02d\n", size, lib, val, dat->mday, dat->mon + 1);
Я не могу себе представить способ легко построить эту строку (и она не использует чередовать варианты (#
))
И так как он существует в основном для совместимость причины — в конце концов, почти вся стандартная библиотека C пригодна для использования из C ++ — я не могу себе представить, почему это потребует дальнейшей интеграции.
Нет, но вы могли бы написать это достаточно легко, например:
template<typename T>
char const *format_specifier();
template<> inline char const *format_specifier<int>() { return "%d"; }
// ... in function
int d = 5;
printf(format_specifier<decltype(d)>, d);
Это довольно грубо, хотя ИМХО и все еще подвержено ошибкам. Вероятно, почему этого нет в стандартной библиотеке.
Лучшее решение, которое использует форматирование в стиле printf, было бы кодировать:
my_printf("bla % bla % bla", arg1, arg2, arg3);
где %
просто получает правильный тип из аргумента. Вы можете сделать это с помощью шаблонов с переменными значениями, и уже есть несколько популярных реализаций этого.