从 gcc/clang 检索编译时已知的值

问题描述 投票:0回答:3

考虑以下由

 定义的编译时间常数 
VALUE

struct foo  {  uint32_t a;  };

static constexpr int VALUE = sizeof(foo);

请注意,此处计算值的方式并不重要。

我想检索值本身(示例中为 4)作为编译的结果;换句话说,我不想构建一个二进制文件并启动它来获取这个值。

我知道选项

-E
允许在预处理后停止,但在此阶段该值尚不清楚。也许存在一些编译器选项可以允许这样做,但我不知道。

我能想到的唯一办法就是放一个会导致错误的

static_assert(VALUE==-1)
,并希望错误消息能保存该值;似乎
gcc
可以做到这一点,但
clang
不行。

是否有更好的方法且不依赖于编译器来获取编译本身的常量值?

c++ g++ clang++
3个回答
4
投票

这个:

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
  • icx
    error: implicit instantiation of undefined template 'error<4>'
  • msvc
    error C2079: 'print' uses undefined class 'error<4>'

编译器资源管理器上亲自查看。在所有这些上,您可以 grep

error<[0-9]+>
来检索 4.


0
投票

利用用户生成的

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
模式,否则它根本无法解析。


0
投票

要在编译时识别枚举的值,请在枚举定义后更新 #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;
}
© www.soinside.com 2019 - 2024. All rights reserved.