我有幾個類都以 uint8 緩沖區的形式接收原始資料,緩沖區中資料的基礎資料型別在運行時決定。緩沖區需要通過一個模板化的轉換器函式,并在運行時在一個大的 switch 陳述句中決定,這取決于接收到的資料型別將要執行哪個模板化版本的轉換器函式。所以我有一個“內部”轉換器函式和一個“外部”開關函式,它根據底層資料的資料型別呼叫“內部”函式的不同模板版本。由于“內部”轉換器函式看起來都有些不同,所以到目前為止,我對每個“內部”函式都有一個單獨的“外部”函式。
現在我想做一個更通用的“外部”函式,它可以將“內部”函式作為輸入引數。但是我對如何進行模板化有點困惑。
這是我目前的做法:
struct InputParams
{
size_t num_elements;
size_t num_bytes_per_vec;
};
struct OutputData
{
float *q0;
float *q1;
};
template <typename T> OutputData testFunction(const uint8_t* const input_data, const InputParams& input_params)
{
OutputData output;
// Allocate 'output' in some way...
const T* const t_ptr = reinterpret_cast<const T* const>(input_data);
for(size_t k = 0; k < input_params.num_elements; k )
{
output.q0[k] = input_data[k];
output.q1[k] = ...
// ...
}
return output;
}
template <typename O, template <typename> typename F, typename T, typename I>
O applyFunctionForDataType(const uint8_t* const input_data,
const DataType data_type,
const F<T>& converter_function,
const I& input_params)
{
O output_data;
if (data_type == DataType::FLOAT)
{
output_data = converter_function<float>(input_data, input_params);
}
else if (data_type == DataType::DOUBLE)
{
output_data = converter_function<double>(input_data, input_params);
}
else if (data_type == DataType::INT8)
{
output_data = converter_function<int8_t>(input_data, input_params);
}
else if ...
return output_data;
}
模板引數typename O和typename I用于輸出資料結構和輸入引數,因為它們因將呼叫所有這些的函式而異。在一個用例中,OutputData可能有兩個 float 指標,在另一個用例中,一個 float 指標和一個 int 指標。InputParams可能總是非常相似,但我想我也可以將其作為模板引數,因為OutputData已經是一個了。
打電話applyFunctionForDataType:
InputParams input_params;
OutputData oo = applyFunctionForDataType<OutputData>(data_ptr_, data_type_, testFunction, input_params);
我從編譯器收到以下錯誤訊息:
<source>:68:23: error: 'converter_function' does not name a template but is followed by template arguments
output_data = converter_function<float>(input_data, input_params);
^ ~~~~~~~
<source>:61:40: note: non-template declaration found by name lookup
const F<T>& converter_function,
編譯測驗
當然歡迎替代解決方案。
uj5u.com熱心網友回復:
您不能將函式模板傳遞給您的模板。但是,您可以傳遞一個提供模板函式的物件:
template <typename O, typename Converter, typename I>
O applyFunctionForDataType(const uint8_t* const input_data,
const DataType data_type,
Converter&& converter,
const I& input_params)
{
O output_data;
if (data_type == DataType::FLOAT)
{
output_data = std::forward<Converter>(converter).template Convert<float>(input_data, input_params);
}
else if (data_type == DataType::DOUBLE)
{
output_data = std::forward<Converter>(converter).template Convert<double>(input_data, input_params);
}
else if (data_type == DataType::INT8)
{
output_data = std::forward<Converter>(converter).template Convert<int8_t>(input_data, input_params);
}
return output_data;
}
struct TestFunctionConverter
{
template<class T>
OutputData Convert(const uint8_t* const inputData, const InputParams& inputParams) const
{
return testFunction<T>(inputData, inputParams);
}
};
int main()
{
...
OutputData oo = applyFunctionForDataType<OutputData>(input_data, dt, TestFunctionConverter{}, input_params);
}
或者你可以傳遞一個型別作為模板模板引數,它提供了一個轉換函式:
template <typename O, template <typename> class Converter, typename I>
O applyFunctionForDataType(const uint8_t* const input_data,
const DataType data_type,
const I& input_params)
{
O output_data;
if (data_type == DataType::FLOAT)
{
output_data = Converter<float>{}(input_data, input_params);
}
else if (data_type == DataType::DOUBLE)
{
output_data = Converter<double>{}(input_data, input_params);
}
else if (data_type == DataType::INT8)
{
output_data = Converter<int8_t>{}(input_data, input_params);
}
return output_data;
}
template<class T>
struct TestFunctionConverter
{
OutputData operator()(const uint8_t* const inputData, const InputParams& inputParams) const
{
return testFunction<T>(inputData, inputParams);
}
};
int main()
{
...
OutputData oo = applyFunctionForDataType<OutputData, TestFunctionConverter>(input_data, dt, input_params);
...
}
uj5u.com熱心網友回復:
基本上模板不會那樣作業。模板總是在編譯時決議,不同的模板函式特化有不同的地址,所以你不能通過一個函式引數傳遞它們。您需要以某種方式傳遞所有可能的變體。無論是論點:
template <typename O, typename I>
O applyFunctionForDataType(const uint8_t* const input_data,
const DataType data_type,
O(*converter_function_float)(const uint8_t* const, const InputParams&),
O(*converter_function_double)(const uint8_t* const, const InputParams&),
const I& input_params)
{
...
}
// Calling
InputParams input_params;
OutputData oo = applyFunctionForDataType<OutputData>(data_ptr_, data_type_, testFunction<float>, testFunction<double>, input_params);
或者您可以使用std::arrayorstd::vector或std::map將這些函式傳遞到一個引數中,然后根據data_type變數選擇需要的函式。
template <typename O>
using converter_function_type = O(*)(const uint8_t* const, const InputParams&);
template <typename O, typename I>
O applyFunctionForDataType(const uint8_t* const input_data,
const DataType data_type,
std::map<DataType, converter_function_type<O>> converters,
const I& input_params)
{
return converters[data_type](input_data, input_params);
}
std::map<DataType, converter_function_type<OutputData>> cnv_funcs = {
{DataType::FLOAT, testFunction<float>},
{DataType::DOUBLE, testFunction<double>},
};
int main()
{
InputParams input_params;
const uint8_t* const input_data = new uint8_t[20];
DataType dt = DataType::DOUBLE;
OutputData oo = applyFunctionForDataType<OutputData>(input_data, dt, cnv_funcs, input_params);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/534073.html
標籤:C 模板
