【问题标题】:Template Instantiation Source file and Line Number, From where it is being called模板实例化源文件和行号,从哪里调用
【发布时间】:2016-03-15 00:53:05
【问题描述】:

在以下代码中:

   template< typename T, typename ValueType>
   bool SomeFunction(
        SomeWrapper<T> volatile& ioTarget,
        ValueType inCompare,
        ValueType inNewValue)
    {
         BOOST_STATIC_ASSERT(sizeof(SomeWrapper<T>) == sizeof(int));
    }

Boost Static Assert 因编译时错误而失败。

Getting sizeof(T) 帮助我在编译时获得了大小作为警告。

在分析 Compiler Message 时,它​​并没有精确指向进行此模板化调用的实际源代码位置。

是否有任何其他模板化技术可用于获取有关实际源代码文件和调用此函数的行的信息。

PS:我曾想过 __FILE__ ,但这是一个宏在编译时没有帮助。

【问题讨论】:

    标签: c++ templates boost compilation template-meta-programming


    【解决方案1】:

    您可以通过其他方式使您的代码失败,从而使编译器输出您需要的信息。这可以例如在断言失败的情况下进行一些不完整的模板实例化。 例如,编译以下代码:

    template<bool>
    struct tester;
    
    template<>
    struct tester<true> { }; // only define template for 'true'
    
    template<class T>
    void func(T t)
    {
       tester<sizeof(T) == sizeof(int)>();
    }
    
    int main()
    {
       int i;
       func(i);   // <- this call is ok :)
       double d;
       func(d);   // <- this is line 18, the offending call :(
       return 0;
    }
    

    在使用gcc 编译时给我以下输出:

    g++-4.9 -O3 -fexpensive-optimizations -Drestrict= -std=c++11 -o main main.cpp  -pthread
    main.cpp: In instantiation of ‘void func(T) [with T = double]’:
    main.cpp:18:10:   required from here
    main.cpp:10:4: error: invalid use of incomplete type ‘struct tester<false>’
        tester<sizeof(T) == sizeof(int)>();
        ^
    main.cpp:2:8: error: declaration of ‘struct tester<false>’
     struct tester;
            ^
    

    所以gcc 现在告诉我函数调用是从我的main.cpp 文件的第18 行进行的,正确识别了有问题的行。 这应该能够提供您需要的信息。

    编辑 15/12-15: 要打印编译时警告,您需要触发一个不会导致编译器错误的软错误。这可以例如成为溢出警告。 为了简短起见,代码如下所示:

    ///
    // struct that will overflow and print integer s at compile-time
    ////
    template<unsigned s>
    struct overflow
    {
       operator char() { return (s + 256); }
    };
    
    /////
    // function that will print warning message at compile-time
    // warning message must be made as a class/struct
    ////
    template<class MESSAGE>
    void print_warning(MESSAGE)
    {
       char(overflow<sizeof(MESSAGE)>());
    };
    
    struct this_is_a_warning // warning message
    {
    };
    
    template<class T>
    void func()
    {
       print_warning(this_is_a_warning()); // <- this will print a warning, line 27
    }
    
    int main()
    {
       func<double>(); // <- line 32
       return 0;
    }
    

    gcc 编译这个给我:

    g++-4.9 -O3 -fexpensive-optimizations -Drestrict= -std=c++11 -o main main.cpp  -pthread main.cpp: In instantiation of ‘overflow<s>::operator char() [with unsigned int s = 1u]’: 
    main.cpp:17:4:   required from ‘void print_warning(MESSAGE) [with MESSAGE = this_is_a_warning]’ 
    main.cpp:27:37:   required from ‘void func() [with T = double]’
    main.cpp:32:17:   required from here 
    main.cpp:7:37: warning: overflow in implicit constant conversion [-Woverflow]
        operator char() { return (s + 256); }
    

    'Clearly' 显示函数调用跟踪,以 main.cpp 的第 32 行结束。

    【讨论】:

      【解决方案2】:

      我正在研究 XCode 6.3 LLVM ,但它没有给我它失败的确切行号。 但是在分析 Compiler Logs 时,它会在报告错误后告知此信息。

      所以在错误解决这个问题后查看日志。 现在我能够找到这个实例。

      但这仍然是一个悬而未决的问题,如果该模板成功实例化,是否有任何元编程技术可以在某种警告(不是错误)中说明该模板是从 X 文件和 Y 行号实例化的。

      【讨论】:

      • 我有点回答了最初的问题...添加了一个关于如何获得编译时警告的部分。
      猜你喜欢
      • 1970-01-01
      • 2011-04-06
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 2020-10-27
      • 1970-01-01
      • 2012-05-04
      相关资源
      最近更新 更多