为何__LINE__宏无法与该consteval函数配合使用?
解决MSVC中__LINE__作为模板实参的常量表达式问题
问题描述
我编写了一个小型函数,用于将__LINE__宏转换为wchar_t数组,以便在编译时将行号表示为字符串(无空终止字符):
template <int Line> consteval auto line_number() { auto get_num_digits{ [](int num) consteval { auto count{1}; while (num /= 10) ++count; return count; } }; constexpr auto num_digits{ get_num_digits(Line) }; std::array<wchar_t, num_digits> digits; auto line{ Line }; for (auto i{ num_digits - 1 }; i >= 0; --i) { digits[i] = L'0' + (line % 10); line /= 10; } return digits; }
当通过line_number<123>()调用该函数时一切正常,但使用line_number<__LINE__>()调用时,MSVC 2022 C++20编译器报错称__LINE__不是常量表达式——尽管它是预定义宏。我尝试过__LINE__ + 0或__LINE__ + 4 - (2 * 2)这类写法,希望编译器将其处理为常量,但均无效。
奇怪的是,IntelliSense能将__LINE__识别为常量,可正确计算函数返回值,但编译器却不认可。
解决方法
方法1:宏包装__LINE__
MSVC在处理预定义宏作为模板非类型实参时存在特殊逻辑,通过宏包装可以强制编译器将__LINE__视为编译期常量:
#define LINE_CONSTANT (__LINE__) // 调用示例 auto line_arr = line_number<LINE_CONSTANT>();
方法2:constexpr变量中转
用constexpr变量存储__LINE__的值,再将其作为模板实参传递:
constexpr int current_line = __LINE__; auto line_arr = line_number<current_line>();
方法3:调整编译器选项
确保已启用C20及以上标准(编译选项/std:c++20或/std:c++latest),同时可以尝试添加/Zc:preprocessor选项,启用符合C标准的预处理器行为,这能修复MSVC对__LINE__的常量识别问题。
方法4:修改函数实现,移除模板实参依赖
将函数改为直接接受constexpr行号参数,而非模板实参,这样无需处理模板实参的常量验证问题:
consteval auto line_number(int Line) { auto get_num_digits{ [](int num) consteval { auto count{1}; while (num /= 10) ++count; return count; } }; constexpr auto num_digits{ get_num_digits(Line) }; std::array<wchar_t, num_digits> digits; auto line{ Line }; for (auto i{ num_digits - 1 }; i >= 0; --i) { digits[i] = L'0' + (line % 10); line /= 10; } return digits; } // 调用示例 auto line_arr = line_number(__LINE__);
内容的提问来源于stack exchange,提问作者Arush Agarampur
相关产品推荐
相关产品推荐

