Printf like checks #62
Comments
Unfortunately the
This library uses variadic templates (emulated on pre-C++11) instead of varargs because varargs are inherently unsafe. While it doesn't provide compile-time warnings for literal format strings, it catches all type errors and reports them as exception. Unlike the |
thanks for fast reply, but sometime it not good practice to use exceptions. I will think about possibility to deal with new c++11&(14) functions may be some idea from this post http://akrzemi1.wordpress.com/2011/05/11/parsing-strings-at-compile-time-part-i/ |
Thanks for the suggestion and the link. I think this can be used to catch at least some errors in literal format strings. Whether this is really practical needs further investigation though. Reopening the issue. |
i've just found solution on some Russian resource |
Fascinating. To make this practical, however, the whole As the translation is not very good, here's a link to the same blog post in Russian for future reference: http://habrahabr.ru/post/142352/ |
without changing a syntax it's not possible the only one way to do this something like |
With the recent improvements to the library (passing argument type information separately from the arguments themselves), I think it might be possible to safely use varargs and the |
It occurred to me that you can have compile-time checking of #include "format.h"
void check_args(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
#define FMT_PRINTF(...) \
if (false) check_args(__VA_ARGS__); \
fmt::printf(__VA_ARGS__);
int main() {
try {
FMT_PRINTF("%s", 42);
} catch (const std::exception &e) {
fmt::print("error: {}\n", e.what());
}
} Compiling it with GCC gives the desired warning:
And if you ignore the warning, it's still safe. You get an exception at runtime:
|
Looking at various options:
So (1) will not work here while (2) and (3) don't look particularly appealing. Therefore I'm going to close this issue until a better option is found. |
As discussed on Reddit it might be possible to use UDL for compile-time checks:
Example: #include <iostream>
#define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#include <boost/hana.hpp>
namespace hana = boost::hana;
using namespace hana::literals;
template<typename String, typename... Ts>
void foo(String fmt, Ts...) {
if constexpr (hana::is_a<hana::string_tag>(fmt)) {
static_assert(hana::back(fmt) != '{', "Why would you end your format string with '{'?");
if constexpr (hana::back(fmt) != '{') { return; }
(hana::size(fmt) - hana::size_c<1>).times.with_index([&](auto i) {
if constexpr (fmt[i] == '{') {
static_assert(fmt[i + hana::size_c<1>] == '}', "This is an example and only supports empty '{}', dummy.");
}
});
} else {
std::cout << "We don't have a compile-time string. We can still use it: " << fmt << "\n";
}
}
int main() {
//foo("abc"_s);
//foo("abc {} def"_s);
foo("abc def {"_s);
//foo("abc {foo} def"_s);
//foo("abc def");
} |
Compile-time format string checks are now available: http://zverovich.net/2017/11/05/compile-time-format-strings.html |
some compilers (gcc,clang) can check printf like functions
in Os X it works like this
int printf(const char * __restrict, ...) __printflike(1, 2);
int sprintf(char * __restrict, const char * __restrict, ...) __printflike(2, 3);
int sscanf(const char * __restrict, const char * __restrict, ...) __scanflike(2, 3);
int vsprintf(char * __restrict, const char * __restrict, va_list) __printflike(2, 0);
int snprintf(char * __restrict, size_t, const char * __restrict, ...) __printflike(3, 4);
int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list) __printflike(3, 0);
define __printflike(fmtarg, firstvararg) \
i fink it good idea to add something similar to your library
you can take some additional information here https://mail-index.netbsd.org/tech-userlevel/2012/03/04/msg006197.html
The text was updated successfully, but these errors were encountered: