怎么修改能使它支持输入函数或者变量
时间: 2023-12-05 07:05:54 浏览: 29
要支持输入函数或变量,需要将传入的参数进行求值。可以使用 C++11 中的可变参数模板和 std::forward 来实现。
具体的做法是:
1. 定义一个递归函数 `toJson()`,它会将传入的参数转换为 JSON 对象,并将其添加到上一级对象中。对于函数或变量,它会将其值求出并转换为字符串。如果无法求值,可以将其转换为字符串,但需要在 JSON 中标记为未求值。
2. 在 `JSONLOG()` 中,使用可变参数模板来遍历传入的参数,对每个参数调用 `toJson()`,并将结果添加到 JSON 对象中。
下面是修改后的代码:
```c++
template<typename T>
rapidjson::Value toJson(T&& value, rapidjson::Document::AllocatorType& allocator) {
rapidjson::Value jsonValue;
if constexpr(std::is_invocable_v<decltype(value)>) {
try {
auto result = value();
jsonValue = toJson(result, allocator);
} catch(...) {
jsonValue.SetString("failed to evaluate function", allocator);
}
} else {
jsonValue.SetString(std::forward<T>(value), allocator);
}
return jsonValue;
}
void toJson(rapidjson::Value& object, rapidjson::Document::AllocatorType& allocator) {}
template<typename Head, typename... Tail>
void toJson(rapidjson::Value& object, rapidjson::Document::AllocatorType& allocator, Head&& head, Tail&&... tail) {
rapidjson::Value value = toJson(std::forward<Head>(head), allocator);
object.AddMember(rapidjson::StringRef(std::forward<Head>(head)), value, allocator);
toJson(object, allocator, std::forward<Tail>(tail)...);
}
#define JSONLOG(...) { \
rapidjson::Document doc; \
doc.SetObject(); \
auto allocator = doc.GetAllocator(); \
doc.AddMember("filename", __FILE__, allocator); \
rapidjson::Value message(rapidjson::kObjectType); \
toJson(message, allocator, #__VA_ARGS__); \
doc.AddMember("message", message, allocator); \
rapidjson::StringBuffer jsonbuffer; \
rapidjson::Writer<rapidjson::StringBuffer> writer(jsonbuffer); \
doc.Accept(writer); \
std::cout << jsonbuffer.GetString() << std::endl; \
}
```
这样,当传入的参数是函数或变量时,会自动求值并转换为 JSON 对象。如果无法求值,会在 JSON 中标记为未求值。