我有一个格式化字符串的函数:
template<typename ... Args>
inline std::string format(const std::string & format, Args ... args)
{
std::size_t size = MINIGINE_FORMAT_PRINTF(nullptr, 0, format.c_str(), args ...) + 1; // +1 for NULL terminated
std::unique_ptr<char[]> buf( new char[ size ] );
MINIGINE_FORMAT_PRINTF(buf.get(), size, format.c_str(), args ...);
return std::string(buf.get(), buf.get() + size - 1); // -1 we don't want NULL terminated
}
问题在于,当我调用此函数时:
format("%d", "");
警告显示在模板化功能中,而不是在呼叫站点。
是否可以在调用网站中显示格式警告,而不是模板化功能?
答案 0 :(得分:0)
我提出了解决问题的解决方案。 如果编译器为格式生成警告,则警告将显示在调用宏的行上。
我在下面测试了模板化格式函数和下面的宏: https://godbolt.org/ 当模板化函数的格式参数是const char *而不是std :: string
时,它们似乎都生成相同的代码#pragma once
#include <string>
#include <memory>
#ifdef _MSC_VER
#define MINIGINE_FORMAT_PRINTF _snprintf
#else
#define MINIGINE_FORMAT_PRINTF snprintf
#endif
#define MINIGINE_FORMAT(format, ...) \
/*Capture everything by reference*/[&] /*No arguments*/() \
{ \
std::size_t size = MINIGINE_FORMAT_PRINTF(nullptr, 0, format, __VA_ARGS__) + 1; \
std::unique_ptr<char[]> buf( new char[ size ] ); \
MINIGINE_FORMAT_PRINTF(buf.get(), size, format, __VA_ARGS__); \
return std::string(buf.get(), buf.get() + size - 1); \
} /*Call the lambda*/()
答案 1 :(得分:0)
是否可以在呼叫站点而非模板功能中显示格式警告?
是的,您可以使用constexpr
格式的字符串检查在几乎没有宏的情况下执行此操作。例如:
template <typename S, typename... Args>
inline std::string format(const S &fmt, const Args &... args) {
constexpr bool is_valid = check_format_string<Args...>(fmt);
// Do formatting.
}
其中check_format_string
是constexpr
函数,用于解析和检查格式字符串,而S
是compile-time format string。
{fmt} library中使用了此技术,该技术实现了类似Python的格式:
// test.cc
#define FMT_STRING_ALIAS 1
#include <fmt/format.h>
std::string s = format(fmt("{2}"), 42);
在呼叫站点编译并观察预期的错误:
$ c++ -Iinclude -std=c++14 test.cc
...
test.cc:4:17: note: in instantiation of function template specialization 'fmt::v5::format<S, int>' requested here
std::string s = format(fmt("{2}"), 42);
^
include/fmt/core.h:778:19: note: non-constexpr function 'on_error' cannot be used in a constant expression
ErrorHandler::on_error(message);
^
include/fmt/format.h:2226:16: note: in call to '&checker.context_->on_error(&"argument index out of range"[0])'
context_.on_error("argument index out of range");
^
您仍然需要一个宏来构建编译时字符串,但这在C ++ 20中是不必要的。
免责声明:我是{fmt}的作者。