C ++模板类型在typedef工作的地方中断

时间:2013-01-10 15:28:14

标签: c++ templates compiler-errors typedef

我目前被IMHO奇怪的问题困扰:使用模板打破编译,使用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-less。我不想讨论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同意在使用模板时出现问题。那么我在这里做错了什么?

2 个答案:

答案 0 :(得分:3)

当您使用模板时,请

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,请参阅此主题:

答案 1 :(得分:1)

如果sample_T是模板参数,则kissfft_t::cpx_type是从属名称。在实例化模板之前,编译器无法推断它是一个类型名称,因此需要将其写为typename kissfft_t::cpx_type

如果它不是模板参数,那么将typename置于错误状态,所以不幸的是,无论是否{{1},你都需要添加更多可怕的预处理器恶作剧。 }已定义。