c ++ возврат из шаблона

Я немного новичок в общем программировании с использованием шаблонов на 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

Любая помощь в исправлении этого приветствуется. Кроме того, было бы здорово, если бы я мог получить ссылки на учебник, который объясняет различные концепции, используемые в этом коде.

EDIT-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 (Вот) похоже отличается от того что я имею в этой функции. Может ли это быть проблемой? Если да, то как я могу это исправить, поскольку, насколько я понимаю, эти типовые имена на самом деле не являются «типами».

Благодарю.

-1

Решение

Проблема заключается в вашем определении BuildVanillaNetwork функционировать как:

mlpack::ann::FFN<> BuildVanillaNetwork(...)

Сообщения об ошибках обычно трудно читать человеку, когда они включают шаблоны, но чтение строк дает вам что-то вроде этого:

ошибка: неверное количество аргументов шаблона (0, должно быть 4) … предусмотрено для класса шаблона mlpack :: ann :: FFN ’

Остальные ошибки вызваны этой (в основном, потому что он не понимает тип возврата этой функции, компилятор предполагает, что это intто жалуется что не может конвертировать net в int).

Таким образом, вы должны указать аргументы шаблона для возвращаемого типа. Вы используете decltype в теле функции, чтобы вывести их (что происходит во время компиляции, а не во время выполнения), но в прототипе это будет не так просто. Есть способ использовать decltype объявить тип возвращаемого значения функции, но это не поможет вам в этом случае. Таким образом, вы могли бы также пойти и написать их явно.

0

Другие решения

mlpack::ann::FFN<> BuildVanillaNetwork(MatType& trainData,

Измените его на то, что включает в себя параметры из шаблона, например:

mlpack::ann::FFN<
PerformanceFunction,
OutputLayerType,
PerformanceFunctionType,
MatType
> BuildVanillaNetwork(MatType& trainData,...

Или попробуй decltype (авто) если ваш компилятор поддерживает это:

auto BuildVanillaNetwork(MatType& trainData,`...) -> decltype(auto) {...
0

Вы можете использовать следующий шаблон для в некотором роде упростить вывод типа возврата:

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(...);
0
По вопросам рекламы [email protected]