考虑以下由
定义的编译时间常数
VALUE
struct foo { uint32_t a; };
static constexpr int VALUE = sizeof(foo);
请注意,此处计算值的方式并不重要。
我想检索值本身(示例中为 4)作为编译的结果;换句话说,我不想构建一个二进制文件并启动它来获取这个值。
我知道选项
-E
允许在预处理后停止,但在此阶段该值尚不清楚。也许存在一些编译器选项可以允许这样做,但我不知道。
我能想到的唯一办法就是放一个会导致错误的
static_assert(VALUE==-1)
,并希望错误消息能保存该值;似乎gcc
可以做到这一点,但clang
不行。
是否有更好的方法且不依赖于编译器来获取编译本身的常量值?
这个:
template<auto> class error;
error<VALUE> print;
打印:
error: implicit instantiation of undefined template 'error<4>'
error: aggregate 'error<4> print' has incomplete type and cannot be defined
error: implicit instantiation of undefined template 'error<4>'
error C2079: 'print' uses undefined class 'error<4>'
在编译器资源管理器上亲自查看。在所有这些上,您可以 grep
error<[0-9]+>
来检索 4.
利用用户生成的
static_assert
消息 (P2741R3) 的 C++26 功能,您可以计算要在编译时发出的任何字符串:
// This can be replaced with `fmt::format("{}", x)`, or constexpr `std::format` in future C++ versions
consteval std::string to_string(std::integral auto x) {
std::string result;
constexpr std::size_t max_size = std::numeric_limits<decltype(x)>::digits10 + 2;
result.resize_and_overwrite(max_size, [&x](char* p, std::size_t count) -> std::size_t {
assert(count == max_size);
auto [ last, ec ] = std::to_chars(p, p + max_size, x, 10);
assert(ec == std::errc{});
return last - p;
});
return result;
}
static constexpr int VALUE = sizeof(foo);
static_assert(false, "MARKER'" + ::to_string(VALUE) + "'MARKER");
// Compiler error output contains "MARKER'4'MARKER", which you can search for
您可以有任何您想要的消息。也许是一个
constexpr
JSON 库,用于更复杂的输出。
GCC 声称在 GCC 14 中支持这一点。它甚至接受它作为旧 C++ 版本中的扩展。
Clang 从 Clang 17 开始就支持这一点,但你必须处于
-std=c++2c
模式,否则它根本无法解析。
要在编译时识别枚举的值,请在枚举定义后更新 #define 的简单列表,并使用它
enum Booze {
GIN = 20000,
VINE,
VODKA
};
#define DEF_GIN Booze::GIN
#define DEF_VINE Booze::VINE
#define DEF_VODKA Booze::VODKA
int main () {
int vin ((int) VINE);
std::cout << "VINE = " << vin << std::endl;
return 0;
}