如何在C++中打印编译时计算的结果?

Dmi*_*yal 9 c++ gcc static-assert constexpr c++11

我写了几个constexpr函数,并在static_asserts中使用它们来控制一些资源限制.但是我不仅要强制执行编译时谓词,还要查看在正常编译过程中计算的实际值,或者至少在断言失败时.

有很多方法可以在编译期间打印字符串消息,但是打印constexpr计算的结果是什么?

toh*_*ava 6

下面是一些代码,利用gcc的诊断消息在断言消息后打印感兴趣的值.要查找感兴趣的值,您只需要搜索错误字符串T x =:

#include <string>

template <class T, T x, class F>
void transparent(F f) { f(); }


template <bool B>
constexpr void my_assert() { 
    static_assert(B, "oh no");
}

template <int X>
void f() {
    transparent<int, X+7>([]{
        transparent<long, X*X*X>([]{
            my_assert<X+10==-89>(); });});
}

int main() {
//    f<3>();
    f<4>();
//    f<-99>();
}
Run Code Online (Sandbox Code Playgroud)

这是它给我带来的错误:

g++ h.cpp -std=c++11 h.cpp: In instantiation of ‘constexpr void my_assert() [with bool B = false]’: h.cpp:16:34: required from ‘f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:15:35: required from ‘struct f() [with int X = 4]::__lambda0::__lambda1’ h.cpp:16:38: required from ‘f() [with int X = 4]::__lambda0’ h.cpp:14:28: required from ‘struct f() [with int X = 4]::__lambda0’ h.cpp:16:41: required from ‘void f() [with int X = 4]’ h.cpp:21:10: required from here h.cpp:9:5: error: static assertion failed: oh no static_assert(B, "oh no"); ^ h.cpp:4:6: error: ‘void transparent(F) [with T = long int; T x = 64l; F = f() [with int X = 4]::__lambda0::__lambda1]’, declared using local type ‘f() [with int X = 4]::__lambda0::__lambda1’, is used but never defined [-fpermissive] void transparent(F f) { f(); } ^ h.cpp:4:6: error: ‘void transparent(F) [with T = int; T x = 11; F = f() [with int X = 4]::__lambda0]’, declared using local type ‘f() [with int X = 4]::__lambda0’, is used but never defined [-fpermissive]

注意粗体部分


Mic*_*pso 6

这是基于@tohava 发布解决方案

如果您需要打印不带 的 constexpr 值static_assert(),这适用于带有-Wunused标志的 GCC 编译器:

// before c++17:
template <typename T, T val>
constexpr void static_print() {
    #if !defined(__GNUC__) || defined(__clang__)
        int static_print_is_implemented_only_for_gcc = 0;
    #else
        int unused = 0;
    #endif
};

// for c++17 and higher:
template <auto val>
constexpr void static_print() {
    #if !defined(__GNUC__) || defined(__clang__)
        int static_print_is_implemented_only_for_gcc = 0;
    #else
        int unused = 0;
    #endif
};

int main() {
    constexpr int i = 13;
    // for c++17 and higher:
    static_print<i>();
    // before c++17:
    static_print<int, i>();
}
Run Code Online (Sandbox Code Playgroud)

输出:

$ g++ -std=c++17 main.cpp -Wall && ./a
main.cpp: In instantiation of 'constexpr void static_print() [with auto val = 13]':
main.cpp:23:21:   required from here
main.cpp:17:7: warning: unused variable 'unused' [-Wunused-variable]
   int unused = 0;
       ^~~~~~
main.cpp: In instantiation of 'constexpr void static_print() [with T = int; T val = 13]':
main.cpp:24:26:   required from here
main.cpp:8:7: warning: unused variable 'unused' [-Wunused-variable]
   int unused = 0;
       ^~~~~~
Run Code Online (Sandbox Code Playgroud)

重要的部分是val = 13.

https://godbolt.org/z/Cdb-At在线玩这个例子

不幸的是,Clang 编译器不包括警告消息的回溯,因此它不输出值。