C function pointer
function pointer
以下是宣告function pointer的方式:
/*
int square(int x){
return x * x;
}
*/
int (*fnc_ptr)(int) = □
function pointer是一種指向一段可執行代碼起始位置的指標。在上例中,fnc_ptr
指向的是square
這個函數。我們可以使用如下方式來調用它:
std::cout << (*fnc_ptr)(10) << std::endl;
注意到我們使用&
來獲取square
函數的位置,並使用*
來從function pointer中獲取函數本身。但其實我們也可以用函數名本身獲取其地址,如下例:
int (*fnc_ptr2)(int) = square;
std::cout << fnc_ptr2(10) << std::endl;
可以看到,省略square
前的&
及fnc_ptr2
的*
後,代碼仍可運行。
typedef function pointer
在上例中,如果我們想定義一個指向"接受一個int參數,回傳int"的函數指標,就得使用:
int (*fnc_ptr)(int);
事實上我們可以運用typedef
,這樣就使用較簡單的語法來達到相同的目的:
typedef int(*MyFnc)(int);
MyFnc f = square;
std::cout << f(10) << std::endl;
以上寫法看著不太自然,但如果我們把MyFnc
用它的定義int(*MyFnc)(int)
來做替換,就會變成:
int(*f)(int) = square;
即,使用typedef
前的寫法,完整代碼詳見cpp-code-snippets/function_pointer.cpp。
在TensorRT/parsers/caffe/caffeParser/opParsers/opParsers.h
中也使用了typedef
來定義一個function pointer型別:
typedef nvinfer1::ILayer* (*LayerParseFn)(nvinfer1::INetworkDefinition&, const trtcaffe::LayerParameter&, CaffeWeightFactory&, BlobNameToTensor&);
這裡定義:接受 nvinfer1::INetworkDefinition&, const trtcaffe::LayerParameter&, CaffeWeightFactory&, BlobNameToTensor&
為參數,回傳 nvinfer1::ILayer*
的函數指標名為LayerParseFn
。
function pointer as template argument
既然functoin pointer是一種型別,那麼我們還可以將它用作template的參數來用。例如,在TensorRT/parsers/caffe/caffeParser/opParsers/opParsers.h
中定義了一個unordered_map
,其mapped_type為LayerParseFn
:
nvinfer1::ILayer* parseConvolution(nvinfer1::INetworkDefinition& network, const trtcaffe::LayerParameter& msg, CaffeWeightFactory& weightFactory, BlobNameToTensor& tensors);
//...
static std::unordered_map<std::string, LayerParseFn> gParseTable
{
{"Convolution", parseConvolution},
{"Pooling", parsePooling},
{"InnerProduct", parseInnerProduct},
{"ReLU", parseReLU},
{"Softmax", parseSoftMax},
{"SoftmaxWithLoss", parseSoftMax},
{"LRN", parseLRN},
{"Power", parsePower},
{"Eltwise", parseEltwise},
{"Concat", parseConcat},
{"Deconvolution", parseDeconvolution},
{"Sigmoid", parseSigmoid},
{"TanH", parseTanH},
{"BatchNorm", parseBatchNormalization},
{"Scale", parseScale},
{"Crop", parseCrop},
{"Reduction", parseReduction},
{"Reshape", parseReshape},
{"Permute", parsePermute},
{"ELU", parseELU},
{"BNLL", parseBNLL},
{"Clip", parseClip},
{"AbsVal", parseAbsVal},
{"PReLU", parsePReLU}
};
在TensorRT/parsers/caffe/caffeParser/caffeParser.cpp
中的CaffeParser::parse
則如此使用gParseTable
:
auto v = gParseTable.find(layerMsg.type());
if (v == gParseTable.end())
{
//...
}
else
{
ILayer* layer = (*v->second)(network, layerMsg, weights, *static_cast<BlobNameToTensor*>(mBlobNameToTensor));
//...
}
此處的*v->second
是為LayerParseFn
型別的函數,因此我們可以傳參數進去,也可以期待它回傳一個ILayer*
型別的值出來。