C ++格式字符串宏

时间:2016-12-03 09:06:30

标签: c++ c-preprocessor string-formatting compiler-warnings

我有一个格式化字符串的函数:

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", "");

警告显示在模板化功能中,而不是在呼叫站点。

是否可以在调用网站中显示格式警告,而不是模板化功能?

2 个答案:

答案 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_stringconstexpr函数,用于解析和检查格式字符串,而Scompile-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}的作者。