c++ - 调试模板实例化

标签 c++ c++11

在使用 C++ 模板进行元编程时,是否可以使用一种方法(有点像调试器)来逐步了解模板是如何被实例化和编译的?现在看来,当创建一个复杂的模板网络时,除了查看编译器错误消息以查看模板是如何被实例化的(如果有任何编译器错误)之外,确实没有很好的调试方法,如果正在生成意外的东西,则尝试从错误消息中向后工作。我不确定我正在寻找的东西是否存在,因为它必须是在编译时完成的事情,但基本上它是一种方法,有点像单步执行代码并检查堆栈帧gdb 在运行时,可以停止编译器并检查环境以了解实例化模板或嵌套模板集的顺序。

例如,假设我创建了一些简单的代码,如下所示:

template<typename T, typename R = void>
struct int_return_type {};

template<typename R>
struct int_return_type<int, R>
{
    typedef R type;
};

template<typename T, typename R = void>
struct float_return_type {};

template<typename R>
struct float_return_type<float, R> 
{
    typedef R type;
};

template<typename T>
typename int_return_type<T>::type test()
{
    cout << "T type is int" << endl;
}

template<typename T>
typename float_return_type<T>::type test()
{
    cout << "T type is float" << endl;
}

int main()
{
    test<int>();
    test<float>();
    return 0;
}

我知道这是相对容易遵循的代码,但模板可能会涉及更多,尤其是在进行元编程、递归等时。我知道编译器会发出错误消息,可用于推断模板的方式正在实例化,但我也想知道当实际模板代码在语法意义上是正确的,但运行时结果仍然不正确时可以做什么。例如,最好有一个方法来停止编译器并查看正在实例化的 test 以及 int_return_typefloat_return_type有,或者什么实例化失败了。

是目前唯一可用于调试具有这种粒度级别的模板的选项 1) 代码不正确时的编译器错误消息,以及 2) 反汇编器和调试器的组合,以查看在运行时生成了哪些实例化代码 -时间结果不正确?还是有一些其他实用程序可以帮助“观察”模板是如何实例化的,并查看/检查编译器生成了哪些代码来调查和调试模板错误?

最佳答案

这些是非常基本的,但在大多数情况下它们对我有用。我也很想看看其他人怎么说。

为人为的例子道歉。

使用沙盒

从小沙箱开始测试模板代码,一旦它开始表现怪异或者您正在做一些复杂的事情。我对模板非常满意,而且我仍然几乎立即这样做。简而言之,它可以更快地发现错误。你在这里为我们做了这件事,所以我认为这没有实际意义。

指定临时类型

临时人员可能会混淆您的意图未得到满足的地方。我已经看到很多类似下面的代码。

template<typename T>
  T calc(const T &val) {
    return some_other_calc(val) / 100.0;
  }

告诉编译器你期望什么类型会更快地失败,并且可能会给你一个更好的消息来处理。

template<typename T>
  T calc(const T &val) {
    T val_ = some_other_calc(val);
    return val_ / 100.0;
  }

使用 typeid

使用 typeid(T).name() 在调试语句中打印模板名称。这将为您提供一个字符串,您可以使用它来查看编译器如何决定满足该类型。

template<typename T>
  typename void test() {
    std::cout << "testing type " << typeid(T).name() << std::endl;
    // ...
  }

避免不必要的默认实现

以它们没有默认实现的方式编写模板。

template<typename T, bool is_integral = boost::is_numeric<T>::value >
  struct my_traits;

template<typename T>
  struct my_traits<T, true> {
    typedef uint32_t cast_type;
  };

template<typename T>
  void print_whole_number(T &val) {
    std::cout << static_cast<my_traits<T>::cast_type>(val) << std::endl;
  }

这强制 print_whole_number 的用户拥有自己的 my_traits 特化。他们将得到一个编译器错误,而不是 half 工作,因为您无法为所有类型提供良好的实现。诚然,如果将编译器错误用于代码库的不同部分,编译器错误不会立即产生帮助。

关于c++ - 调试模板实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7325910/

相关文章:

c++ - 获取不带 -g 标志的 gdb 可读符号?

c++ - 什么是好的游戏随机数生成器?

c++ - std::enable_if 是如何工作的?

c++ - 如何使用线程每 0.3 秒发送一次消息?

c++ - typedef结构问题

c++ - 为嵌套容器制作模板函数

c++ - 我们应该如何实现对象类型的 move ?

c++ - void* 和 char* 的区别

c++ - const_iterator 和迭代器有什么区别?

c++ - 2个默认复制构造函数: is it possible?