debugging模板实例
在使用C ++模板进行元编程时,是否有一种方法可以像debugging器一样使用,以便逐步实现模板的实例化和编译? 现在看来,在创build一个复杂的模板networking时,除了查看编译器错误消息以查看如何实例化模板(如果有任何编译器错误)之外,确实没有很好的debugging方法,并尝试从错误信息后退工作,如果意想不到的事情正在产生。 我不确定是否存在我正在寻找的东西,因为它必须是在编译时完成的东西,但基本上它会是一个方法,就像是逐步执行代码并检查堆栈框架gdb
在运行时,在那里编译器可以停止,环境检查模板或嵌套模板集实例化的序列。
例如,我们假设我创build了一些简单的代码,如下所示:
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; }
我知道这是相对简单的代码要遵循,但模板可以得到更多的介入,特别是当进行元编程,recursion等。我明白,编译器将发布错误消息,可以用来推断如何实例化模板,但是我也想知道当实际的模板代码在语法上是正确的时候可以做什么,但是运行时结果仍然不正确。 实例中有一个方法可以停止编译器,并查看哪个test
以及int_return_type
和float_return_type
正在被实例化,或哪些实例失败。
目前唯一可用的选项是用于debugging具有这种粒度级别的模板1)代码不正确时的编译器错误消息,以及2)反汇编程序和debugging程序的组合,以查看运行时结果是否生成了实例化代码不正确的? 还是有一些其他的实用工具,帮助“观察”如何实例化模板,并查看/检查编译器生成什么代码来调查和debugging模板错误?
这些都是非常基本的,但是在大多数情况下它们都适用于我。 我很想看看别人也有什么要说的。
道歉的人为的例子。
使用沙箱
从小沙箱开始testing模板代码,只要它开始行为怪异,或者你正在做一些复杂的事情。 我对模板非常舒服,而且我几乎立即做到这一点。 简而言之,它可以更快地发现错误。 你已经在这里为我们做了,所以我认为这是没有意义的。
指定临时types
临时会混淆你的意图不符合的地方。 我已经看到了很多类似下面的代码。
template<typename T> T calc(const T &val) { return some_other_calc(val) / 100.0; }
告诉编译器,你期待什么types将会更快失败,并且可能会给你一个更好的信息来处理。
template<typename T> T calc(const T &val) { T val_ = some_other_calc(val); return val_ / 100.0; }
使用typeid
使用typeid(T).name()
在debugging语句中打印模板名称。 这会给你一个string,你可以使用它来看看编译器是如何实现这个types的。
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
专业化。 他们会得到一个编译器错误,而不是一半的工作,因为你不能提供一个好的实现所有types。 如果在代码库的不同部分使用编译器错误,那么编译器错误将不会立即有用。
是的,有一个模板元编程debugging器。 Templight
我喜欢使用优秀的基于Web的Comeau编译器进行debugging。 它可以注意到在其他编译器不能…的标准compilance方面的错误…
Comeau有比GCC或MSVC提供更多可读错误消息的巨大优势。
另外,请记住在任何可能的地方使用static_assert
,即使您确定答案是正确的。