宏定义错误 - 未提供有效的预处理标记
Error in Macro Definition - does not give a valid preprocessing token
有一个非常简单的cpp代码。
文件名:file.cpp
#include "file.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
Message_t msg;
memset(&msg,0,sizeof(Message_t));
msg.message_id = 1234;
strcpy(msg.message,"data");
Message_Descriptor_t desc ;
memset(&desc, 0, sizeof(Message_Descriptor_t));
desc.no_of_fields = 2;
desc.fields = malloc(2 * sizeof(Field_Descriptor_t));
strcpy(desc.fields[0].var_name, "message_id");
desc.fields[0].type = FIELD_INT;
strcpy(desc.fields[1].var_name, "message");
desc.fields[1].type = FIELD_CHAR;
char *json_string = "";
BUILD_MSG(msg,desc,json_string);
}
文件名:file.hpp
#ifndef _FILE_HPP_
#define _FILE_HPP_
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef struct Message_s
{
int message_id;
char *message;
} Message_t;
typedef enum
{
FIELD_INT = 0,
FIELD_CHAR = 1
} FieldType_e;
typedef struct Field_Descriptor_s
{
char *var_name;
FieldType_e type;
} Field_Descriptor_t;
typedef struct Message_Descriptor_s
{
int no_of_fields;
Field_Descriptor_t *fields;
} Message_Descriptor_t;
#define BUILD_STRING(key, value ,json_string) \
{ \
strcat(json_string, key); \
strcat(json_string, "|"); \
strcat(json_string, value. ## key); \
}
#define BUILD_INT(key, value ,json_string) \
{ \
strcat(json_string, key); \
strcat(json_string, "|"); \
char buffer [33]; \
strcat(json_string, key); \
}
#define BUILD_MSG(msg, msg_descriptor, json_string) \
{ \
for (int i=0; i < msg_descriptor.no_of_fields; i++) \
{ \
Field_Descriptor_t field = msg_descriptor.fields[i]; \
char *var_name = NULL; \
strcpy(var_name, field.var_name); \
switch(field.type) \
{ \
case FIELD_CHAR: \
BUILD_STRING(var_name, msg, json_string); \
break; \
case FIELD_INT: \
BUILD_INT(var_name, msg, json_string); \
break; \
default: \
break; \
} \
} \
}
#define BUILD_JSON_MSG (msg, msg_descriptor, json_string) \
{ \
BUILD_MSG(msg,msg_descriptor); \
}
#endif
出现以下编译错误:
g++ -c file.cpp
In file included from file.cpp:1:
file.cpp:25:1: error: pasting "." and "var_name" does not give a valid preprocessing token
file.cpp: In function 'int main()':
file.cpp:18: error: invalid conversion from 'void*' to 'Field_Descriptor_t*'
file.cpp:25: error: 'struct Message_t' has no member named 'var_name'
在上面的例子中,json_string 的逻辑是为了虚拟目的而填充的。
我们如何通过引用另一个包含存储的成员变量名称的描述符结构来访问结构的成员变量。
提前致谢。
经过长时间的交谈,我弄清楚了你想要做什么,并且能够用现代 C++ 重写它。这是我想出的:
#include <string>
#include <vector>
#include <variant>
#include <iostream>
#include <unordered_map>
using Field_t = std::variant<int, std::string>;
using Message_t = std::unordered_map<std::string, Field_t>;
using Field_Descriptor_t = std::string;
using Message_Descriptor_t = std::vector<Field_Descriptor_t>;
struct Visitor {
std::string &json_string;
void operator()(const int value) {
json_string += std::to_string(value);
}
void operator()(const std::string &value) {
json_string += value;
}
};
void buildMsg(const Message_t &msg, const Message_Descriptor_t &desc, std::string &json_string) {
Visitor visitor{json_string};
for (const Field_Descriptor_t &field : desc) {
json_string += field;
json_string += '|';
std::visit(visitor, msg.at(field));
json_string += '\n';
}
}
int main() {
Message_t msg;
msg["message_id"] = 1234;
msg["message"] = "data";
Message_Descriptor_t desc;
desc.push_back("message_id");
desc.push_back("message");
std::string json_string;
buildMsg(msg, desc, json_string);
std::cout << json_string;
}
这个程序的输出是:
message_id|1234
message|data
Message_Descriptor_t
参考 Message_t
对我来说似乎没有必要。它似乎增加的唯一好处是秩序。代码可以进一步简化,与原始代码几乎没有相似之处。
#include <string>
#include <vector>
#include <variant>
#include <iostream>
using Key = std::string;
using Value = std::variant<int, std::string>;
using Pair = std::pair<Key, Value>;
using Message = std::vector<Pair>;
struct Stringify {
std::string &output;
void operator()(const int value) {
output += std::to_string(value);
}
void operator()(const std::string &value) {
output += value;
}
};
void stringifyMessage(std::string &output, const Message &message) {
for (const Pair &pair : message) {
output += pair.first;
output += '|';
std::visit(Stringify{output}, pair.second);
output += '\n';
}
}
int main() {
Message message;
message.emplace_back("message_id", 1234);
message.emplace_back("message", "data");
std::string output;
stringifyMessage(output, message);
std::cout << output;
}
将此与问题中的原始类 C C++ 代码进行比较,您就会明白为什么我如此喜欢 C++。
有一个非常简单的cpp代码。
文件名:file.cpp
#include "file.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int main()
{
Message_t msg;
memset(&msg,0,sizeof(Message_t));
msg.message_id = 1234;
strcpy(msg.message,"data");
Message_Descriptor_t desc ;
memset(&desc, 0, sizeof(Message_Descriptor_t));
desc.no_of_fields = 2;
desc.fields = malloc(2 * sizeof(Field_Descriptor_t));
strcpy(desc.fields[0].var_name, "message_id");
desc.fields[0].type = FIELD_INT;
strcpy(desc.fields[1].var_name, "message");
desc.fields[1].type = FIELD_CHAR;
char *json_string = "";
BUILD_MSG(msg,desc,json_string);
}
文件名:file.hpp
#ifndef _FILE_HPP_
#define _FILE_HPP_
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
typedef struct Message_s
{
int message_id;
char *message;
} Message_t;
typedef enum
{
FIELD_INT = 0,
FIELD_CHAR = 1
} FieldType_e;
typedef struct Field_Descriptor_s
{
char *var_name;
FieldType_e type;
} Field_Descriptor_t;
typedef struct Message_Descriptor_s
{
int no_of_fields;
Field_Descriptor_t *fields;
} Message_Descriptor_t;
#define BUILD_STRING(key, value ,json_string) \
{ \
strcat(json_string, key); \
strcat(json_string, "|"); \
strcat(json_string, value. ## key); \
}
#define BUILD_INT(key, value ,json_string) \
{ \
strcat(json_string, key); \
strcat(json_string, "|"); \
char buffer [33]; \
strcat(json_string, key); \
}
#define BUILD_MSG(msg, msg_descriptor, json_string) \
{ \
for (int i=0; i < msg_descriptor.no_of_fields; i++) \
{ \
Field_Descriptor_t field = msg_descriptor.fields[i]; \
char *var_name = NULL; \
strcpy(var_name, field.var_name); \
switch(field.type) \
{ \
case FIELD_CHAR: \
BUILD_STRING(var_name, msg, json_string); \
break; \
case FIELD_INT: \
BUILD_INT(var_name, msg, json_string); \
break; \
default: \
break; \
} \
} \
}
#define BUILD_JSON_MSG (msg, msg_descriptor, json_string) \
{ \
BUILD_MSG(msg,msg_descriptor); \
}
#endif
出现以下编译错误:
g++ -c file.cpp
In file included from file.cpp:1:
file.cpp:25:1: error: pasting "." and "var_name" does not give a valid preprocessing token
file.cpp: In function 'int main()':
file.cpp:18: error: invalid conversion from 'void*' to 'Field_Descriptor_t*'
file.cpp:25: error: 'struct Message_t' has no member named 'var_name'
在上面的例子中,json_string 的逻辑是为了虚拟目的而填充的。
我们如何通过引用另一个包含存储的成员变量名称的描述符结构来访问结构的成员变量。
提前致谢。
经过长时间的交谈,我弄清楚了你想要做什么,并且能够用现代 C++ 重写它。这是我想出的:
#include <string>
#include <vector>
#include <variant>
#include <iostream>
#include <unordered_map>
using Field_t = std::variant<int, std::string>;
using Message_t = std::unordered_map<std::string, Field_t>;
using Field_Descriptor_t = std::string;
using Message_Descriptor_t = std::vector<Field_Descriptor_t>;
struct Visitor {
std::string &json_string;
void operator()(const int value) {
json_string += std::to_string(value);
}
void operator()(const std::string &value) {
json_string += value;
}
};
void buildMsg(const Message_t &msg, const Message_Descriptor_t &desc, std::string &json_string) {
Visitor visitor{json_string};
for (const Field_Descriptor_t &field : desc) {
json_string += field;
json_string += '|';
std::visit(visitor, msg.at(field));
json_string += '\n';
}
}
int main() {
Message_t msg;
msg["message_id"] = 1234;
msg["message"] = "data";
Message_Descriptor_t desc;
desc.push_back("message_id");
desc.push_back("message");
std::string json_string;
buildMsg(msg, desc, json_string);
std::cout << json_string;
}
这个程序的输出是:
message_id|1234
message|data
Message_Descriptor_t
参考 Message_t
对我来说似乎没有必要。它似乎增加的唯一好处是秩序。代码可以进一步简化,与原始代码几乎没有相似之处。
#include <string>
#include <vector>
#include <variant>
#include <iostream>
using Key = std::string;
using Value = std::variant<int, std::string>;
using Pair = std::pair<Key, Value>;
using Message = std::vector<Pair>;
struct Stringify {
std::string &output;
void operator()(const int value) {
output += std::to_string(value);
}
void operator()(const std::string &value) {
output += value;
}
};
void stringifyMessage(std::string &output, const Message &message) {
for (const Pair &pair : message) {
output += pair.first;
output += '|';
std::visit(Stringify{output}, pair.second);
output += '\n';
}
}
int main() {
Message message;
message.emplace_back("message_id", 1234);
message.emplace_back("message", "data");
std::string output;
stringifyMessage(output, message);
std::cout << output;
}
将此与问题中的原始类 C C++ 代码进行比较,您就会明白为什么我如此喜欢 C++。