【问题标题】:Print deduced template arguments at compile time在编译时打印推导出的模板参数
【发布时间】:2021-09-01 17:47:07
【问题描述】:

如何在编译时打印自动推导出的模板参数?

std::pair x(1, 2.0);

在上面的例子中,x 的类型是 std::pair。有没有办法在编译时打印推断出的 x 类型,例如作为 std::pair 还是其他可读形式?

编辑。我正在使用一个依赖于 C++ 17 自动模板参数推导的库 (DPC++)。有时很难猜测模板参数是如何推导出来的。

【问题讨论】:

  • “打印”是什么意思?你的意思是你想得到一个字符串来命名x的完整类型?
  • “打印”是指编译器消息。

标签: c++ visual-studio gcc c++17


【解决方案1】:

这是一种(诚然是迂回和冗长的)方法:

#include <utility>

template <class T>
struct type_reader {
    type_reader() {
        int x{0};
        if (x = 1) {} // trigger deliberate warning
    }
};

int main() {
    std::pair x(1, 2.0);
    type_reader<decltype(x)> t;
}

根据您的编译器和设置,您可能会收到类似警告

<source>:7:19: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        if (x = 1) {} // trigger deliberate warning
<source>:13:34: note: in instantiation of member function 'type_reader<std::pair<int, double>>::type_reader' requested here
    type_reader<decltype(x)> t;

如果你眯着眼睛,你可以看到std::pair&lt;int, double&gt;&gt;的类型。

【讨论】:

    【解决方案2】:

    在我看来,您问的是两个不同且独立的问题。

    1. 给定一个从 CTAD 获得的对象,如何获得该对象的推导确切类型。

    对于这个问题,答案很简单:这是 decltype() 的作品,它允许一些东西

    std::pair x{1, 2.0};
    
    decltype(x) y{2, 3.0};  // y is std::pair<int, double>
    
    static_assert( std::is_same_v<decltype(x), std::pair<int, double>> );
    static_assert( std::is_same_v<decltype(y), std::pair<int, double>> );
    
    1. 如何以人类可读的形式打印对象的类型?

    C++ 提供了一个运算符typeid(),它返回一个类的对象std::type_info,其中包括一个name() 方法,该方法返回该类型的C 样式字符串描述。

    所以你可以写

    std::pair x{1, 2.0};
    
    std::cout << typeid(x).name() << '\n';
    

    不幸的是,描述字符串是特定于实现的,对于非平凡的类型,对于人类来说并不是真正的描述。

    例如,从那段代码中,我得到

    St4pairIidE
    

    来自 g++ 和

    NSt3__14pairIidEE
    

    来自 clang++。

    显然,如果您对为std::pair 推导出的模板参数感兴趣,您可以推导出单个类型(intdouble)并打印出来。

    例如,你可以写一个函数如下

    template <typename T1, typename T2>
    void print_pair_types (std::pair<T1, T2> const &)
     {
       std::cout << "First pair type: " << typeid(T1).name() << std::endl;
       std::cout << "Second pair type: " << typeid(T2).name() << std::endl;
     }
    

    并使用x 调用它

    std::pair x{1, 2.0};
    
    print_pair_types(x);
    

    我从 g++ 和 clang++ 获得

    First pair type: i
    Second pair type: d
    

    【讨论】:

      【解决方案3】:

      到目前为止,我发现在编译时打印任何东西的推断类型的最快和最简单的方法是将其除以nullptr

      #include <tuple>
      
      int main() {
          auto a = std::make_tuple(0, 10ul, +[](int&&) -> int { return 42; });
          a / nullptr;
      }
      

      GCC 的输出如下所示:

       In function 'int main()':
      5:7: error: no match for 'operator/' (operand types are 'std::tuple<int, long unsigned int, int (*)(int&&)>' and 'std::nullptr_t')
      

      【讨论】:

        猜你喜欢
        • 2015-12-29
        • 2016-09-12
        • 1970-01-01
        • 1970-01-01
        • 2021-12-30
        • 2014-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多