简体   繁体   English

类似函数的宏不接受嵌套的 #define

[英]Function-like macro not accepting nested #define

I am using macros to determine a variable's real type based on a pattern, and I am getting some weird macro errors that I do not understand:我正在使用宏根据模式确定变量的真实类型,但出现了一些我不明白的奇怪的宏错误:

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.

Why is this happening?为什么会这样? I have no idea, please provide some help if you know why.我不知道,如果你知道为什么,请提供一些帮助。

#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

As I understood the motivation of the OP's question the intention is:据我了解,OP 提出问题的动机是:

  • to parse text解析文本
  • determine a certain type of input确定某种类型的输入
  • store the value in that type.将值存储在该类型中。

Types of variables have to be defined at compile time.变量类型必须在编译时定义。 (That's one of the C++ language core concepts called static type checking . There is no chance to define a type of a variable at runtime.) (这是 C++ 语言核心概念之一,称为 静态类型检查。没有机会在运行时定义变量的类型。)

So, all the types which shall be supported have to defined in the source code at the same time.因此,所有应支持的类型必须同时在源代码中定义。

As an input term may always have at most one of these types, the storage of the values may consider that.由于输入项可能始终最多具有这些类型中的一种,因此值的存储可能会考虑到这一点。

In C, a union would come in mind but C++ provides something even better: std::variant .在 C 中,会想到联合,但 C++ 提供了更好的东西: std::variant

The variant will be defined with all supported types but an instance will always store a value of one of them.变体将使用所有支持的类型定义,但实例将始终存储其中之一的值。 The type is chosen in the assignment depending of the right hand side.在分配中根据右侧选择类型。

An example to demonstrate that in action:一个在行动中证明这一点的例子:

#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';
  }
}

Output:输出:

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在coliru上进行现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM