c++ - 类似于函数的宏不接受嵌套的#define

标签 c++ regex macros preprocessor

我正在使用宏根据模式确定变量的实类型,并且遇到了一些我不理解的奇怪的宏错误:

a.cpp:15:4: error: '#' is not followed by a macro parameter
                #define USING_INTEGER\
                 ^
a.cpp:15:11: error: unknown type name 'USING_INTEGER'
                #define USING_INTEGER\
                        ^
a.cpp:16:2: error: expected unqualified-id
        else if (matchRegex(DOUBLE_REGEX, val))\
        ^
3 errors generated.
为什么会这样呢?我不知道,如果您知道原因,请提供一些帮助。
#include "example_3.cpp"
#include <regex>

std::string INT_REGEX = "^[-+]?\\d+$",
            DOUBLE_REGEX = "^[-+]?\\d+\\.\\d?$",
            BOOLEAN_REGEX = "^(true|false)$";

bool matchRegex(std::string pattern, std::string inputString) {
    std::regex expression(pattern);
    return std::regex_match(inputString, expression);
}

#define determineType(var)\
    if (matchRegex(INT_REGEX, val))\
        #define USING_INTEGER\
    else if (matchRegex(DOUBLE_REGEX, val))\
        #define USING_DOUBLE\
    else if (matchRegex(BOOLEAN_REGEX, val))\
        #define USING_BOOL\
    else\
        #define USING_RAW

最佳答案

据我了解OP的问题的动机,目的是:

  • 解析文本
  • 确定输入的特定类型
  • 以该类型存储值。

  • 变量类型必须在编译时定义。
    (这是称为static type checking的C++语言核心概念之一。
    在运行时没有机会定义变量的类型。)
    因此,必须在源代码中同时定义所有应支持的类型。
    由于输入项可能始终最多具有这些类型中的一种,因此值的存储可以考虑到这一点。
    在C语言中,会想到union,但是C++提供了更好的东西:std::variant
    将使用所有受支持的类型定义该变体,但实例将始终存储其中之一的值。在分配中根据右侧选择类型。
    一个实例来证明这一点:
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <variant>
    
    // an error type
    struct None { std::string text; };
    
    // a value what can represent one of all supported types
    typedef std::variant<bool, int, double, std::string, None> Value;
    
    // reads a value from a text determining its type
    Value readInput(const std::string &text)
    {
      // check for int
      { std::istringstream in(text); int value;
        if (in >> value && in.tellg() == -1) {
          return Value(value);
        }
      }
      // check for floating point
      { std::istringstream in(text); double value;
        if (in >> value && in.tellg() == -1) {
          return Value(value);
        }
      }
      // check for bool
      if (text == "true") return Value(true);
      if (text == "false") return Value(false);
      // check for (quoted) string
      if (text.size() >= 2
        && ((text.front() == '"' && text.back() == '"')
        || (text.front() == '\'' && text.back() == '\''))) {
        return Value(text.substr(1, text.size() - 2));
      }
      // ERROR
      return Value(None{ text });
    }
    
    // prints the value (considering the current type)
    void print(const Value &value)
    {
      switch (value.index()) {
        case 0: std::cout << "bool: " << std::boolalpha << std::get<bool>(value); break;
        case 1: std::cout << "int: " << std::get<int>(value); break;
        case 2: std::cout << "double: " << std::get<double>(value); break;
        case 3: std::cout << "string: '" << std::get<std::string>(value) << '\''; break;
        case 4: std::cout << "ERROR! text: '" << std::get<None>(value).text << '\''; break;
        default: std::cout << "Value not initialized.";
      }
    }
    
    int main()
    {
      const std::string tests[] = {
        "true", // bool
        "false", // bool
        "123", // int
        "123.17", // double
        "0", // int
        "0.0", // double
        "'text'", // string
        "''", // string
        "something that doesn't match any type" // ERROR
      };
      for (const std::string &test : tests) {
        std::cout << "Test \"" << test << "\"\n";
        const Value value = readInput(test);
        std::cout << "Got: ";
        print(value);
        std::cout << '\n';
      }
    }
    
    输出:
    Test "true"
    Got: bool: true
    Test "false"
    Got: bool: false
    Test "123"
    Got: int: 123
    Test "123.17"
    Got: double: 123.17
    Test "0"
    Got: int: 0
    Test "0.0"
    Got: double: 0
    Test "'text'"
    Got: string: 'text'
    Test "''"
    Got: string: ''
    Test "something that doesn't match any type"
    Got: ERROR! text: 'something that doesn't match any type'
    
    Live Demo on coliru

    关于c++ - 类似于函数的宏不接受嵌套的#define,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63608967/

    相关文章:

    C++ 运算符和参数

    c++ - 在 C++ 字符串上使用标准转换

    c++ - 如何在 C++ 中使用时钟()

    regex - 用于提取子字符串的 POSIX 正则表达式

    compilation - Common Lisp 编译和加载目录

    c++ - 重定向 C++ fstream

    c++ - 如何将有界重复匹配为仅 n 和 m 次

    javascript - 如何在 NetSuite freemarker 模板中按空格分割字符串?

    multithreading - 在Qt5中使用QThreads发出std::string。 Q_DECLARE_METATYPE

    visual-studio - 在 Visual Studio 中运行宏时获取光标位置