Tôi đang sử dụng một số macro ghi nhật ký, có nghĩa vụ in ra thông tin được cung cấp bởi macro __PRETTY_FUNCTION__
và nếu tên và giá trị cần thiết tối đa hai đối số. Một phiên bản đơn giản hóa của mã của tôi trông giống nhưMacro biến thể không có đối số
template<typename Value1, typename Value2>
void Log(std::string const& function,
std::string const& variable_1 = "", Value1 value_1 = Value1(0),
std::string const& variable_2 = "", Value2 value_2 = Value2(0)) {
std::cout << function << " "
<< variable_1 << " " << value_1 << " "
<< variable_2 << " " << value_2 << std::endl;
}
#define LOG0() Log(__PRETTY_FUNCTION__)
#define VARIABLE(value) #value, value
#define LOG1(value) Log(__PRETTY_FUNCTION__, VARIABLE(value))
#define LOG2(value, value1) Log(__PRETTY_FUNCTION__, VARIABLE(value), VARIABLE(value1))
#define LOG(arg0, arg1, arg2, arg, ...) arg
#define CHOOSE(...) LOG(,##__VA_ARGS__, LOG2, LOG1, LOG0)
#define Debug(...) CHOOSE(__VA_ARGS__)(__VA_ARGS__)
tôi có thể sử dụng các macro như
Debug();
int x = 0;
Debug(x);
int y = 1;
Debug(x, y);
Khi tôi biên dịch mã này với kêu vang tôi nhận được một kết quả đẹp có chứa lớp và thông tin chức năng cũng như tên và giá trị của các biến. Nhưng tôi cũng nhận được cảnh báo rằng mã tuân thủ chuẩn không được phép có đối số zerodic.
warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
#define CHOOSE(...) LOG(,##__VA_ARGS__, LOG2, LOG1, LOG0)
^
warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
Debug();
Gcc mặt khác thất bại trong việc biên dịch với
error: expected primary-expression before ‘)’ token
#define LOG1(value) Log(__PRETTY_FUNCTION__, VARIABLE(value))
^
Debug();
Rõ ràng nó là nguy hiểm để làm việc với zero luận variadic.
- Có cách nào để tôi có thể biến mã này thành mã tuân thủ chuẩn mà không loại bỏ sự tiện lợi khi chỉ có một macro mất 0 đến 2 đối số không?
- Nếu điều này là không thể, có cách nào để làm cho gcc cũng biên dịch mã này?
Hành vi của ## __ VA_ARGS__ phụ thuộc vào phiên bản CPP của bạn. Nó có thể đơn giản như thêm khoảng trống trước dấu phẩy trướC##: 'LOG (, ## __ VA_ARGS __, ...' – Pianosaurus
Ngoài ra, các macro của bạn hoạt động như với tôi trong g ++ 4.9.2, ngoại trừ g ++ không thể suy ra loại mẫu của các giá trị khi chúng không được đưa ra. Bạn đã đăng một ví dụ hoàn chỉnh, hoặc là một cái gì đó bị thiếu? – Pianosaurus