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

调试模板实例化 使用C++模板进行元编程时,有没有一种方法可以用来像模板一样,来检查模板是如何被实例化和遵从的?现在看来,在创建复杂的模板网络时,除了查看编译器错误消息以查看模板是如何实例化的(如果存在任何编译器错误)之外,没有很好的调试方法,如果发生意外情况,则尝试从错误消息向后工作。我不确定我要寻找的东西是否存在,因为它必须是在编译时完成的,但基本上它是一种方法,有点像在运行时在gdb中单步遍历代码并检查堆栈帧,可以停止编译器并检查环境以确定模板或一组嵌套模板的实例化顺序,c++,c++11,C++,C++11,例如,假设我创建了一些简单的代码,如下所示: 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_retu

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

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;
}
模板
结构int_返回_类型{};
模板
结构int\u返回类型
{
typedef-R型;
};
模板
结构浮点\返回\类型{};
模板
结构浮点\返回\类型
{
typedef-R型;
};
模板
typename int_return_type::type test()
{

cout我喜欢使用优秀的基于web的Comeau编译器进行调试。它可以注意到标准编译中的错误,而其他编译器无法

Comeau的一大优势是,与GCC或MSVC相比,它提供了更多可读的错误消息


此外,请记住尽可能在任何地方使用
static\u assert
,即使您确信答案是正确的。

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

为人为的例子道歉

使用沙箱

从小沙盒开始,当模板代码开始表现出奇怪的行为或者你正在做一些复杂的事情时,就测试它。我对模板很满意,而且我仍然几乎立即这样做。简单地说,它可以更快地发现错误。你已经为我们做了这件事,所以我认为这是没有意义的

指定临时类型

临时工可能会混淆你的意图没有得到满足的地方

template<typename T>
  T calc(const T &val) {
    return some_other_calc(val) / 100.0;
  }
避免不必要的默认实现

以这样一种方式编写模板:它们没有默认实现

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;
  }
模板
构建我的个性;
模板
构造我的特征{
typedef uint32_t cast_类型;
};
模板
无效打印完整编号(T&val){

std::cout是的,有一个模板元编程调试器。

在2018年我们有。但不确定它对于真正复杂的模板有多有用。

除了
静态断言
之外,对于让你想看的东西出错,我不认为有任何帮助。顺便说一句,我知道这有点离题,但我很好奇,我的代码似乎足够了,否则我不会发布它(没有什么比发布代码更不能编译的了)…您在Comeau编译器中使用了什么设置?@Jason,C++0x扩展的严格模式。没问题…我可以理解您所说的更详细的错误消息的含义。我还注意到与
clang
中的错误消息类似的模式。您对该编译器有什么想法吗?如果我决定离开
gcc
,是否还有其他负面影响,如减少与GNU工具链实用程序的集成,如
binutils
gdb
,等等?@Jason:Clang生成的代码应该与gdb兼容,如果不是,你可以提交一个bug。它与模板和宏的错误消息是可读的,并且没有错误(目前)正在努力获得“模板差异化”功能;即能够向用户指出两种不匹配的模板类型的确切差异。Comeau编译器的网站已关闭,因此这不再是一个选项。+1以这样的方式编写模板:它们没有默认实现。尽管:(不过Metashell仍在积极开发中:它基于叮当声,远远落后于最近的标准。
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;
  }