在 C++ 中,模板是强大的工具。只需将数据类型作为参数来传递,则无需重写编码也可支持不同数据类型。模板在编译时展开,就像宏一样。区别在于,编译器会在模板展开之前执行类型检查。源代码包含模板函数和类定义,但编译的代码可包含相同函数或类的多个副本。类型参数、非类型参数、默认实参、标量实参和模板参数均可传递给模板,编译器会在其中对函数或类进行相应的例化。
- 支持常用 C++ 模板功能特性。
- 内核之间受支持的数据类型 (T) 和连接类型:
- 数据类型 (T):
int8
、uint8
、int16
、uint16
、cint16
、int32
、uint32
、cint32
、int64
、uint64
、float
和cfloat
重要: 在模板串流连接中,不支持acc48
和cacc48
数据类型。 - 函数参数类型:
input_window<T>
、output_window<T>
、input_stream<T>
和output_stream<T>
- 数据类型 (T):
- 编译器不支持预编译模板内核报头。
函数模板
函数模板源代码定义了可用于不同数据类型的泛型函数。函数模板示例:
// add.h
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_window<ELEMENT_TYPE>* in,
output_window<ELEMENT_TYPE>* out);
// add.cpp
template<typename ELEMENT_TYPE, int FACTOR, size_t NUM_SAMPLES> void add(input_window<ELEMENT_TYPE>* in,
output_window<ELEMENT_TYPE>* out)
{
for (int i=0; i<NUM_SAMPLES; i++)
{
ELEMENT_TYPE value = window_readincr(in);
value += FACTOR;
window_writeincr(out, value);
}
}
// graph.h
mygraph()
{
k[0] = kernel::create(add<int32, 6, 8>);
k[1] = kernel::create(add<int16, 3, 8>);
for (int i=0; i<NUM_KERNELS; i++)
{
runtime<ratio>(k[i]) = 0.3;
source(k[i]) = "src/add.cpp";
}
connect<window<32>>(in[0], k[0].in[0]);
connect<window<32>>(k[0].out[0], out[0]);
connect<window<16>>(in[1], k[1].in[0]);
connect<window<16>>(k[1].out[0], out[1]);
}
其中:
-
add.h 用于定义模板
add()
函数。 -
add.cpp 用于定义
add()
模板函数的代码。 -
graph.h 在
mygraph
类中使用add()
模板函数。
类模板
正如函数模板一样,如果类定义的对象与特定数据类型无关,那么类模板也很有用。类模板示例:
// fir.h
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> class FIR
{
private:
ELEMENT_TYPE (&coeffs)[NUM_COEFFS];
ELEMENT_TYPE tapDelayLine[NUM_COEFFS];
uint32 numSamples;
public:
FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples);
void filter(input_window<ELEMENT_TYPE>* in, output_window<ELEMENT_TYPE>* out);
//user needs to write this function to register necessary info
static void registerKernelClass()
{
REGISTER_FUNCTION(FIR::filter);
REGISTER_PARAMETER(coeffs);
}
};
// fir.cpp
...
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> FIR<NUM_COEFFS, ELEMENT_TYPE>::FIR(ELEMENT_TYPE(&coefficients)[NUM_COEFFS], uint32 samples):coeffs(coefficients)
{
...
}
template<size_t NUM_COEFFS, typename ELEMENT_TYPE> void FIR<NUM_COEFFS, ELEMENT_TYPE>::filter(input_window<ELEMENT_TYPE>* in, output_window<ELEMENT_TYPE>* out)
{
...
}
// graph.h
...
mygraph()
{
k1 = kernel::create_object<FIR<12, int32>>(std::vector<int>({ 180, 89, -80, -391, -720, -834, -478, 505, 2063, 3896, 5535, 6504 }), 8);
runtime<ratio>(k1) = 0.1;
source(k1) = "src/fir.cpp";
headers(k1) = { "src/fir.h" };
k2 = kernel::create_object<FIR<15, int32>>(std::vector<int>({ -21, -249, 319, -78, -511, 977, -610, -844, 2574, -2754, -1066, 18539, 0, 0, 0 }), 8);
runtime<ratio>(k2) = 0.1;
source(k2) = "src/fir.cpp";
headers(k2) = { "src/fir.h" };
...
}
其中:
-
fir.h 用于定义声明类
FIR
的类模板。 -
fir.cpp 包含类
FIR
的实现和类FIR
成员函数filter
的实现。 -
graph.h 演示了
mygraph
类中的模板类FIR
的例化。