从模板返回的 C++ 返回
c++ return from template
我对C++中使用模板进行泛型编程有点陌生,并且对如何从模板化函数返回对象有疑问。这是 mlpack 库的神经网络模块的一部分。这是来自可以在这里找到的feedforward_network_test.cpp。如果我理解正确,模板化函数BuildVanillaNetwork的设置方式,可以传递不同类型的网络参数来构建神经网络。我希望这个函数返回它构建的 FFN 对象,以便我可以从我调用它的地方访问它。我对那里的代码做了一些小的更改:
template <typename PerformanceFunction,
typename OutputLayerType,
typename PerformanceFunctionType,
typename MatType = arma::mat
>
mlpack::ann::FFN<> BuildVanillaNetwork(MatType& trainData,
MatType& trainLabels,
MatType& testData,
MatType& testLabels,
const size_t hiddenLayerSize,
const size_t maxEpochs,
const double classificationErrorThreshold)
{
// input layer
mlpack::ann::LinearLayer<> inputLayer(trainData.n_rows, hiddenLayerSize);
mlpack::ann::BiasLayer<> inputBiasLayer(hiddenLayerSize);
mlpack::ann::BaseLayer<PerformanceFunction> inputBaseLayer;
// hidden layer
mlpack::ann::LinearLayer<> hiddenLayer1(hiddenLayerSize, trainLabels.n_rows);
mlpack::ann::BiasLayer<> hiddenBiasLayer1(trainLabels.n_rows);
mlpack::ann::BaseLayer<PerformanceFunction> outputLayer;
// output layer
OutputLayerType classOutputLayer;
auto modules = std::tie(inputLayer, inputBiasLayer, inputBaseLayer, hiddenLayer1, hiddenBiasLayer1, outputLayer);
mlpack::ann::FFN<decltype(modules), decltype(classOutputLayer), mlpack::ann::RandomInitialization, PerformanceFunctionType> net(modules, classOutputLayer);
net.Train(trainData, trainLabels);
MatType prediction;
net.Predict(testData, prediction);
double classificationError;
for (size_t i = 0; i < testData.n_cols; i++)
{
if (arma::sum(arma::sum(arma::abs(prediction.col(i) - testLabels.col(i)))) != 0)
{
classificationError++;
}
}
classificationError = double(classificationError) / testData.n_cols;
std::cout << "Classification Error = " << classificationError * 100 << "%" << std::endl;
return net;
}
这是主要功能:
int main(int argc, char** argv)
{
arma::mat dataset;
mlpack::data::Load("../data/thyroid_train.csv", dataset, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4, dataset.n_cols - 1);
arma::mat trainLabels = dataset.submat(dataset.n_rows - 3, 0, dataset.n_rows - 1, dataset.n_cols - 1);
mlpack::data::Load("../data/thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4, dataset.n_cols - 1);
arma::mat testLabels = dataset.submat(dataset.n_rows - 3, 0, dataset.n_rows - 1, dataset.n_cols - 1);
const size_t hiddenLayerSize = 8;
const size_t maxEpochs = 200;
const double classificationErrorThreshold = 0.1;
auto myFFN = BuildVanillaNetwork<mlpack::ann::LogisticFunction, mlpack::ann::BinaryClassificationLayer, mlpack::ann::MeanSquaredErrorFunction>
(trainData, trainLabels, testData, testLabels, hiddenLayerSize, maxEpochs, classificationErrorThreshold);
return 0;
}
当我编译它时,我收到以下错误:
[100%] Building CXX object CMakeFiles/ff_nn.dir/src/ff_nn.cpp.o /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:24:18: error: wrong number of template arguments (0, should be 4) mlpack::ann::FFN<> BuildVanillaNetwork(MatType& trainData,
^ In file included from /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:16:0: /usr/local/include/mlpack/methods/ann/ffn.hpp:35:7: error: provided for ‘template<class LayerTypes, class OutputLayerType, class InitializationRuleType, class PerformanceFunction> class mlpack::ann::FFN’ class FFN
^ /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp: In instantiation of ‘int BuildVanillaNetwork(MatType&, MatType&, MatType&, MatType&, size_t, size_t, double) [with PerformanceFunction
= mlpack::ann::LogisticFunction; OutputLayerType = mlpack::ann::BinaryClassificationLayer; PerformanceFunctionType = mlpack::ann::MeanSquaredErrorFunction; MatType = arma::Mat<double>; size_t = long unsigned int]’: /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:83:112: required from here /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:64:12: error: cannot convert ‘mlpack::ann::FFN<std::tuple<mlpack::ann::LinearLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BiasLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BaseLayer<mlpack::ann::LogisticFunction, arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::LinearLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BiasLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BaseLayer<mlpack::ann::LogisticFunction, arma::Mat<double>, arma::Mat<double> >&>, mlpack::ann::BinaryClassificationLayer, mlpack::ann::RandomInitialization, mlpack::ann::MeanSquaredErrorFunction>’ to ‘int’ in return
return net;
^ make[2]: *** [CMakeFiles/ff_nn.dir/src/ff_nn.cpp.o] Error 1 make[1]: *** [CMakeFiles/ff_nn.dir/all] Error 2 make: *** [all] Error 2
任何解决此问题的帮助将不胜感激。此外,如果我能获得一个教程的链接,该教程解释了此代码中使用的各种概念,那就太好了。
编辑-1
我将函数标头更改为:
template <typename PerformanceFunction,
typename OutputLayerType,
typename PerformanceFunctionType,
typename MatType = arma::mat
>
mlpack::ann::FFN<PerformanceFunction, OutputLayerType, PerformanceFunctionType, MatType> BuildVanillaNetwork(MatType& trainData,
MatType& trainLabels,
MatType& testData,
MatType& testLabels,
const size_t hiddenLayerSize,
const size_t maxEpochs,
const double classificationErrorThreshold)
但是我在编译时仍然遇到错误:
[100%] Building CXX object CMakeFiles/ff_nn.dir/src/ff_nn.cpp.o
In file included from /home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:16:0:
/usr/local/include/mlpack/methods/ann/ffn.hpp: In instantiation of ‘class mlpack::ann::FFN<mlpack::ann::LogisticFunction, mlpack::ann::BinaryClassificationLayer, mlpack::ann::MeanSquaredErrorFunction, arma::Mat<double> >’:
/home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:83:112: required from here
/usr/local/include/mlpack/methods/ann/ffn.hpp:361:55: error: incomplete type ‘std::tuple_size<mlpack::ann::LogisticFunction>’ used in nested name specifier
size_t Max = std::tuple_size<LayerTypes>::value - 1,
^
/usr/local/include/mlpack/methods/ann/ffn.hpp:369:55: error: incomplete type ‘std::tuple_size<mlpack::ann::LogisticFunction>’ used in nested name specifier
size_t Max = std::tuple_size<LayerTypes>::value - 1,
^
/home/username/project-yanack/mlpack_nn/src/ff_nn.cpp: In instantiation of ‘mlpack::ann::FFN<PerformanceFunction, OutputLayerType, PerformanceFunctionType, MatType> BuildVanillaNetwork(MatType&, MatType&, MatType&, MatType&, size_t, size_t, double) [with PerformanceFunction = mlpack::ann::LogisticFunction; OutputLayerType = mlpack::ann::BinaryClassificationLayer; PerformanceFunctionType = mlpack::ann::MeanSquaredErrorFunction; MatType = arma::Mat<double>; size_t = long unsigned int]’:
/home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:83:112: required from here
/home/username/project-yanack/mlpack_nn/src/ff_nn.cpp:64:12: error: could not convert ‘net’ from ‘mlpack::ann::FFN<std::tuple<mlpack::ann::LinearLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BiasLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BaseLayer<mlpack::ann::LogisticFunction, arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::LinearLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BiasLayer<arma::Mat<double>, arma::Mat<double> >&, mlpack::ann::BaseLayer<mlpack::ann::LogisticFunction, arma::Mat<double>, arma::Mat<double> >&>, mlpack::ann::BinaryClassificationLayer, mlpack::ann::RandomInitialization, mlpack::ann::MeanSquaredErrorFunction>’ to ‘mlpack::ann::FFN<mlpack::ann::LogisticFunction, mlpack::ann::BinaryClassificationLayer, mlpack::ann::MeanSquaredErrorFunction, arma::Mat<double> >’
return net;
^
make[2]: *** [CMakeFiles/ff_nn.dir/src/ff_nn.cpp.o] Error 1
make[1]: *** [CMakeFiles/ff_nn.dir/all] Error 2
make: *** [all] Error 2
此外,FFN 类(此处)的签名似乎与我在此函数中的签名不同。这可能是一个问题吗?如果是,我该如何解决它,因为据我所知,这些类型名并不是真正的"类型"。
谢谢。
问题是你对BuildVanillaNetwork
函数的定义是:
mlpack::ann::FFN<> BuildVanillaNetwork(...)
当错误消息涉及模板时,通常很难被人类阅读,但通读这些行会给你这样的信息:
错误:模板参数数量错误(0,应为 4)...为"模板类 mlpack::ann::FFN"提供
其余的错误是由这个引起的(基本上,因为它不理解该函数的返回类型,编译器假设它是int
的,然后它抱怨它无法将net
转换为int
)。
因此,您必须实际指定返回类型的模板参数。你在函数主体中使用decltype
来推断它们(这发生在编译时,而不是运行时),但在原型中,这并不容易。有一种方法可以使用decltype
来声明函数的返回类型,但在这种情况下它不会有太大帮助。所以你不妨继续明确地写出来。
mlpack::ann::FFN<> BuildVanillaNetwork(MatType& trainData,
将其更改为包含模板中的参数的内容,例如:
mlpack::ann::FFN<
PerformanceFunction,
OutputLayerType,
PerformanceFunctionType,
MatType
> BuildVanillaNetwork(MatType& trainData,...
或者尝试 decltype(auto) 如果你的编译器支持它:
auto BuildVanillaNetwork(MatType& trainData,`...) -> decltype(auto) {...
可以使用以下模式来简化返回类型推断:
template<typename PerformanceFunction, typename OutputLayerType,
typename PerformanceFunctionType, typename MatType>
struct BuildVanillaNetworkHelper
{
using LinearLayer = mlpack::ann::LinearLayer<>;
using BiasLayer = mlpack::ann::BiasLayer<>;
using BaseLayer = mlpack::ann::BaseLayer<PerformanceFunction>;
using ModulesType = std::tuple<LinearLayer, BiasLayer, BaseLayer,
LinearLayer, BiasLayer, BaseLayer>;
using FFNType = mlpack::ann::FFN<ModulesType, OutputLayerType,
mlpack::ann::RandomInitialization, PerformanceFunctionType>;
};
template <typename PerformanceFunction,
typename OutputLayerType,
typename PerformanceFunctionType,
typename MatType = arma::mat,
typename Helper = BuildVanillaNetworkHelper<
PerformanceFunction, OutputLayerType,
PerformanceFunctionType, MatType>
>
typename Helper::FFNType BuildVanillaNetwork(...);
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 如何取消对nullptr的屏蔽,返回正确的对象
- 奇怪的结构&GCC&clang(void*返回类型)
- 架构决策:返回std::future还是提供回调
- 从python中调用C++函数并获取返回值
- 矩阵向量乘法(cublasDgemv)返回零
- 为什么模板类中的对象不能返回值