含std::chrono的C++代码编译错误:_S_fractional_width问题求助
编译std::chrono相关代码时出现consteval函数未定义错误的原因及解决办法
问题描述
编译使用<std::chrono>库的C++日志模块时,标准库头文件报错:调用consteval函数std::chrono::hh_mm_ss::_S_fractional_width并非常量表达式,提示该函数未定义。项目采用CMake+Clang 14.0.6编译,切换GCC、执行apt更新升级后问题仍存在。
原因分析
- 编译器与标准库兼容性冲突:错误信息显示使用的是GCC 13版本的
libstdc++头文件,但编译器是Clang 14。GCC 13的libstdc++对std::chrono::hh_mm_ss的实现使用了C++20的consteval特性,而Clang 14对该版本libstdc++的consteval实现兼容性不足,导致编译期无法解析函数定义,触发错误。 - 间接依赖触发问题:你的日志代码并未直接使用
std::chrono::hh_mm_ss,但项目中其他依赖<chrono>的文件(如timer.cpp、benchmark_timer.hpp)可能间接实例化了该模板,从而触发错误。
解决办法
- 强制使用Clang自带的libc++:修改CMakeLists.txt,添加编译选项指定使用Clang的标准库,避免与GCC的
libstdc++冲突:set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi") - 升级Clang版本:Clang 15及以上版本对GCC 13的
libstdc++兼容性更好,升级到Clang 15+可解决该问题。 - 降级GCC标准库:若必须使用
libstdc++,可安装GCC 12版本的标准库,通过环境变量或CMake指定使用该版本的头文件与库。 - 排查间接依赖:检查
timer.cpp或benchmark_timer.hpp中是否存在不必要的<chrono>模板使用,若能移除相关代码,可规避错误触发。
相关代码
log.cpp
#include "log.hpp" #include <chrono> #include <iomanip> #include <iostream> #include <utility> #ifdef _WIN32 #include <windows.h> #else #define RESET "\033[0m" #define COLOR_BEGIN(code) "\033[38;2;" << ((code >> 16) & 0xFF) << ";" << ((code >> 8) & 0xFF) << ";" << (code & 0xFF) << "m" #endif namespace Monolith { namespace utils { void log::print_log(std::string &&message) { if (!m_enabled) return; auto now = std::chrono::system_clock::now(); std::time_t time_point = std::chrono::system_clock::to_time_t(now); std::tm *timeinfo = std::localtime(&time_point); auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000; #ifdef _WIN32 HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(console, static_cast<WORD>(m_color)); #else std::cout << COLOR_BEGIN(m_color); #endif std::cout << "[" << m_entity << "] {" << std::put_time(timeinfo, "%T") << ":" << std::setfill('0') << std::setw(3) << milliseconds << "} " << message; #ifdef _WIN32 SetConsoleTextAttribute(console, static_cast<WORD>(0xFFFFFF)); #else std::cout << RESET << std::endl; #endif } std::string format_args(const char *message, va_list args) { const size_t length = 1024; char *buffer = new char[length]; vsnprintf(buffer, length, message, args); std::string result(buffer); delete[] buffer; return result; } log::log(std::string entity, unsigned int color) : m_entity(entity), m_color(color) { } void log::out(const char *message, ...) { va_list args; va_start(args, message); print_log(format_args(message, args)); va_end(args); } } // namespace utils } // namespace Monolith
log.hpp
#pragma once #ifndef _LOG_HPP_ #define _LOG_HPP_ #include <iostream> #include <stdarg.h> namespace Monolith { namespace utils { class log { public: log(std::string entity, unsigned int color); void out(const char *message, ...); private: void print_log(std::string &&message); bool m_enabled = true; std::string m_entity; unsigned int m_color; }; } // namespace utils } // namespace Monolith #endif // !_LOG_HPP_
完整编译错误信息
┌──(recall㉿recall)-[/home/dev/monolith_engine] └─$ ./cmake_build.sh debug -- The C compiler identification is Clang 14.0.6 -- The CXX compiler identification is Clang 14.0.6 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/bin/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Found Vulkan: /usr/lib/x86_64-linux-gnu/libvulkan.so (found version "1.3.250") missing components: glslc glslangValidator -- Configuring done (0.6s) -- Generating done (0.0s) -- Build files have been written to: /home/dev/monolith_engine/build [ 20%] Building CXX object CMakeFiles/monolith.dir/src/utils/log.cpp.o [ 40%] Building CXX object CMakeFiles/monolith.dir/src/main.cpp.o [ 60%] Building CXX object CMakeFiles/monolith.dir/src/utils/timer.cpp.o [ 80%] Building CXX object CMakeFiles/monolith.dir/src/mh_vulkan/renderer/mh_vk_renderer.cpp.o In file included from /home/dev/monolith_engine/src/utils/log.cpp:2: /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: error: call to consteval function 'std::chrono::hh_mm_ss::_S_fractional_width' is not a constant expression static constexpr unsigned fractional_width = {_S_fractional_width()}; ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: note: undefined function '_S_fractional_width' cannot be used in a constant expression /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2275:2: note: declared here _S_fractional_width() ^ In file included from /home/dev/monolith_engine/src/utils/timer.cpp:1: In file included from /home/dev/monolith_engine/src/utils/timer.hpp:5: /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: error: call to consteval function 'std::chrono::hh_mm_ss::_S_fractional_width' is not a constant expression static constexpr unsigned fractional_width = {_S_fractional_width()}; ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: note: undefined function '_S_fractional_width' cannot be used in a constant expression /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2275:2: note: declared here _S_fractional_width() ^ 1 error generated. make[2]: *** [CMakeFiles/monolith.dir/build.make:104: CMakeFiles/monolith.dir/src/utils/log.cpp.o] Error 1 make[2]: *** Waiting for unfinished jobs.... 1 error generated. make[2]: *** [CMakeFiles/monolith.dir/build.make:118: CMakeFiles/monolith.dir/src/utils/timer.cpp.o] Error 1 In file included from /home/dev/monolith_engine/src/mh_vulkan/renderer/mh_vk_renderer.cpp:1: In file included from /home/dev/monolith_engine/src/mh_vulkan/renderer/mh_vk_renderer.hpp:6: In file included from /home/dev/monolith_engine/src/mh_vulkan/renderer/../../core.hpp:31: In file included from /home/dev/monolith_engine/src/mh_vulkan/renderer/../../utils/benchmark_timer.hpp:8: /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: error: call to consteval function 'std::chrono::hh_mm_ss::_S_fractional_width' is not a constant expression static constexpr unsigned fractional_width = {_S_fractional_width()}; ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: note: undefined function '_S_fractional_width' cannot be used in a constant expression /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2275:2: note: declared here _S_fractional_width() ^ In file included from /home/dev/monolith_engine/src/main.cpp:1: In file included from /home/dev/monolith_engine/src/core.hpp:31: In file included from /home/dev/monolith_engine/src/utils/benchmark_timer.hpp:8: /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: error: call to consteval function 'std::chrono::hh_mm_ss::_S_fractional_width' is not a constant expression static constexpr unsigned fractional_width = {_S_fractional_width()}; ^ /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2320:48: note: undefined function '_S_fractional_width' cannot be used in a constant expression /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/chrono:2275:2: note: declared here _S_fractional_width() ^ 1 error generated. make[2]: *** [CMakeFiles/monolith.dir/build.make:90: CMakeFiles/monolith.dir/src/mh_vulkan/renderer/mh_vk_renderer.cpp.o] Error 1 1 error generated. make[2]: *** [CMakeFiles/monolith.dir/build.make:76: CMakeFiles/monolith.dir/src/main.cpp.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/monolith.dir/all] Error 2 make: *** [Makefile:91: all] Error 2
内容的提问来源于stack exchange,提问作者recall
相关产品推荐
相关产品推荐

