【问题标题】:C++ template type breaks where typedef worksC++ 模板类型在 typedef 起作用的地方中断
【发布时间】:2013-01-10 15:28:13
【问题描述】:

我目前被一个恕我直言的奇怪问题难住了:使用模板会破坏编译,而使用 typedef 就可以了。我正在编写的函数旨在从具有以下签名的实值时间序列中确定分析信号

#ifndef USE_TEMPLATE
typedef sample_t sample_T
#else
template<typename sample_T>
#endif
analytic_err analytic(
    size_t length,
    sample_T const * const signal,
    sample_T * const amplitude,
    sample_T * const phase )
{
    typedef kissfft<sample_T> kissfft_t;
    /* ... */

kissfft 是 KissFFT 快速傅立叶变换库的 C++ 变体。再往前几行,我分配了一些工作区数组。

    kissfft_t::cpx_type *inout = new kissfft_t::cpx_type[padded_length];

我故意使用 std::vector 并且我还修改了 Kissfft.hh 以减少 STL。我不想讨论 STL 的使用或不使用。在这个项目中,STL 是不行的(不是我的决定)

这就是麻烦的开始。如果我使用模板变体,即定义从sample_tsample_T 的typedef,一切正常,生成的程序通过所有测试用例。

一旦我切换到使用模板,麻烦就开始了:

GCC 和 Clang 都出现了一些我无法理解的错误:

GCC 错误

In file included from /home/dw/extradev/octuda/src/hilbert_test.cc:6:0:
signalprocess.cc: In function ‘analytic_err analytic(size_t, const sample_T*, samplT*, sample_T*)’:
signalprocess.cc:54:23: error: ‘inout’ was not declared in this scope
signalprocess.cc:54:35: error: expected type-specifier
signalprocess.cc:54:35: error: expected ‘;’
signalprocess.cc: In instantiation of ‘analytic_err analytic(size_t, const sample_T sample_T*, sample_T*) [with sample_T = float; analytic_err = analytic_err_t; size_t = long unsigned int]’:
test_analytic.cc:45:41:   required from here
signalprocess.cc:54:2: error: dependent-name ‘kissfft_t:: cpx_type’ is parsed as a n-type, but instantiation yields a type
signalprocess.cc:54:2: note: say ‘typename kissfft_t:: cpx_type’ if a type is meant
signalprocess.cc:59:2: error: dependent-name ‘kissfft_t:: cpx_type’ is parsed as a n-type, but instantiation yields a type
signalprocess.cc:59:2: note: say ‘typename kissfft_t:: cpx_type’ if a type is meant

Clang 错误

In file included from ../../src/hilbert_test.cc:6:
signalprocess.cc:54:23: error: use of undeclared identifier 'inout'
        kissfft_t::cpx_type *inout = new kissfft_t::cpx_type[padded_length];
                             ^
signalprocess.cc:54:35: error: expected a type
        kissfft_t::cpx_type *inout = new kissfft_t::cpx_type[padded_length];
                                         ^
signalprocess.cc:55:6: error: use of undeclared identifier 'inout'
        if(!inout) {
            ^

and some more all following the same gist.

GCC 和 Clang 同意在使用模板时有些事情是不对的。那么我在这里做错了什么?

【问题讨论】:

    标签: c++ templates compiler-errors typedef


    【解决方案1】:

    当你使用模板时,那么这个

    kissfft_t::cpx_type *inout = new kissfft_t::cpx_type[padded_length];
    

    应该变成这样:

    typename kissfft_t::cpx_type *inout = new typename kissfft_t::cpx_type[padded_length];
    ^^^^^^^^note                              ^^^^^^^^note
    

    因为kissfft_t 依赖于模板参数,因此cpx_type 是一个依赖 类型,因此您需要使用typename 来消除它与静态值的歧义。

    要详细了解为什么需要typename,请参阅此主题:

    【讨论】:

    • 谢谢,解决了!您能否也解释一下,为什么我必须这样做?
    • @datenwolf:更新答案。
    【解决方案2】:

    如果sample_T 是模板参数,则kissfft_t::cpx_type 是从属名称。直到模板实例化,编译器才能推断出它是一个类型名,所以需要写成typename kissfft_t::cpx_type

    如果它不是模板参数,那么输入typename 就会出现错误,所以不幸的是,无论USE_TEMPLATE 是否定义,您都需要添加更多可怕的预处理器恶作剧才能做正确的事情。

    【讨论】:

      猜你喜欢
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多