在编译时解析字符串 - 如果可能的话

时间:2017-12-06 23:26:13

标签: c++11 printf

我正在尝试对printf的格式进行编译时间检查。这是代码。

#include <type_traits>
#include <iostream>

template <typename CHAR, typename ...ARGS>
constexpr size_t trace_cond(CHAR fmt, ARGS&&... args) {
   //always needs to pass
   return 1;
}

template <size_t N, typename ...ARGS>
constexpr size_t trace_cond(const char (&fmt)[N], ARGS&&... args) {
   //return parse(fmt) == args;
   return sizeof...(args) != 0;
}

#define TRACE(fmt, ...) { \
   static_assert(trace_cond(fmt, __VA_ARGS__), "Wrong ARGS"); \
   printf(fmt, ##__VA_ARGS__); \
}

int main(int argc, char* argv[]) {
  //working fine
  TRACE("%d %d\n", 2, 3);

  const char* format = "%d %d\n";
  //error
  TRACE(format, 2, 3);
}

因此,当在编译时知道格式时,我想要检查(使用static_assert),如果它不知道,那么不应该调用检查或总是传递

观测值:

  • 目前代码未编译,因为const char *format is not declared constexpr
  • main不应更改,因为TRACE宏用于大型代码库,但更改为TRACE非常受欢迎

所以我的问题是: 有没有办法在fmt类型为const char *

时跳过static_assert或使其通过

1 个答案:

答案 0 :(得分:0)

我认为您可以通过将static_assert移至trace_cond

来做您想做的事
#include <type_traits>
#include <iostream>

template <size_t C, typename CHAR>
size_t trace_cond(CHAR fmt) {
    //always needs to pass
    return 1;
}

template <typename ...ARGS>
constexpr size_t count_args(ARGS&&... args) {
    return sizeof...(args);
}

template <size_t C, size_t N>
constexpr size_t trace_cond(const char (&fmt)[N]) {
    // TODO, parse fmt and do the needed checks
    static_assert(C == 3, "");
    return 1;
}

#define TRACE(fmt, ...) { \
    trace_cond<count_args(__VA_ARGS__)>(fmt); \
    printf(fmt, ##__VA_ARGS__); \
}

int main(int argc, char* argv[]) {
    // Static check - hard coded to check for 3 arguments
    TRACE("%d %d %d\n", 2, 3, 4);

    const char* format = "%d %d\n";
    // No checks performed
    TRACE(format, 2, 3);
}