【问题标题】:Print a type's name at compile time without aborting compilation?在编译时打印类型的名称而不中止编译?
【发布时间】:2020-05-28 22:14:39
【问题描述】:

在这个问题中:

Print template typename at compile time

我们有一些关于如何让典型的 C++ 编译器在编译时打印类型名称的建议。但是,它们依赖于触发编译错误。

我的问题:我能否让 C++ 编译器在不停止编译的情况下打印类型的名称​​

一般来说,答案是“可能不会”,因为一个有效的程序可以编译到它的目标对象中而不需要在任何地方打印任何东西,所以我特别询问 GCC 和 clang,可能使用预处理器指令、编译器内置函数,或任何特定于编译器的技巧。

注意事项:

  • 显然,挑战在于在using/typedef 语句、模板参数值、可变参数模板等后面打印类型。如果类型明确可用,您可以使用#message "my type is unsigned long long" 之类的东西(如@NutCracker 建议的那样)。但这不是问题的意义所在。
  • 依赖于 C++11 或更早版本的答案优于要求 C++14/17/20 的答案。

【问题讨论】:

  • 我更好奇你为什么需要这个?这应该解决什么问题?
  • @Someprogrammerdude:调试工具 TBH。我只想在遇到一些错误之前打印其中的一些,而不是提前中止编译。
  • @Someprogrammerdude:另一个动机是this one

标签: c++ g++ clang++ compile-time debug-print


【解决方案1】:

gcc 和 clang 提供了一些使用自己的插件的接口,这些插件几乎可以在从解析到代码生成的不同阶段完成所有工作。

接口是特定于编译器的,因为这是一个 gcc 插件,不能用于 clang,反之亦然。

文档很繁琐,这里没有机会详细介绍,所以我只向您指出来自 gcc 和 clang 的文档:

gcc plugin clang plugin

【讨论】:

  • 我认为您的意思是“特定于编译器的”或“特殊的”,而不是“专有的”。
  • 参见维基百科上的this page
  • @einpoklum:感谢您的提示!又学到了一些东西...... :-)
【解决方案2】:

以下机制归功于@JonathanWakely,并且是 GCC 特有的:

int i;

template <typename T>
[[gnu::warning("your type here")]]
bool print_type() { return true; }

bool b = print_type<decltype(i)>();

这给了你:

<source>:In function 'void __static_initialization_and_destruction_0(int, int)':
<source>:7:33: warning: call to 'print_type<int>' declared with attribute warning: your
type here [-Wattribute-warning]
    7 | bool b = print_type<decltype(i)>();
      |          ~~~~~~~~~~~~~~~~~~~~~~~^~

working on Godbolt

【讨论】:

    【解决方案3】:

    在 c++17 中,我们可以滥用[[deprecated]] 属性来强制编译器发出包含所需模板参数的警告:

    template<typename T>
    [[deprecated]] inline constexpr void print_type(T&& t, const char* msg=nullptr){}
    
    print_type(999, "I just want to know the type here...");
    

    上面的 sn-p 将使用 gcc 打印以下警告:

    <source>:32:59: warning: 'constexpr void print_type(T&&, const char*) [with T = int]' is deprecated [-Wdeprecated-declarations]
         print_type(999, "I just want to know the type here...");
    

    与接受的答案相反,这将适用于每个符合 c++17 的编译器。请注意,您必须在 MSVC 上启用 \W3`。

    我们甚至可以更进一步,定义一个静态断言宏,当且仅当它失败时才会打印类型。

    template<bool b, typename T>
    inline constexpr bool print_type_if_false(T&& t) {
        if constexpr (!b)
            print_type(std::forward<T>(t));
        return b;
    }
    
    // Some nice static assert that will print the type if it fails.
    #define STATIC_ASSERT(x,condition, msg) static_assert(print_type_if_false<condition>(x), msg);
    

    Here 是一个活生生的例子。

    【讨论】:

    • 1.这很整洁,谢谢。 2. 为什么要将消息传递给 print_type_if_false?
    • @einpoklum 你说得对,这没有多大意义......我会修复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多