Reputation: 384
I have class which accepts one int
template parameter, and one int
parameter pack (neurons
). One of the constructor's goals is to take each of the parameters in the pack and add an instance of a class to a vector. The class, however, takes its arguments as template parameters.
I have the following code:
template<int iCount, int... neurons>
class network {
private:
std::vector<pl> layers;
public:
network() : layers() {
input_layer<iCount> inp;
layers.push_back(inp);
addLayer<iCount, neurons...>();
}
template<int prev, int nc, int... further>
void addLayer() {
layer<nc, prev> l;
layers.push_back(l);
addLayer<nc, further...>(); // error is here
}
};
The recursive call, which is labeled with 'error is here', produces a compiler error: "Error 4 error C2783: 'void network<1,3,2,1>::addLayer(void)' : could not deduce template argument for 'nc'"
pl
is the parent class of both input_layer
and layer
.
At the moment, I using network
like so:
network<1, 3,2,1> n;
After invoking the constructor, I would expect that n.layers would contain four elements. The first being an input_layer
, to which iCount
was passed, and the remained being layer
s with the corresponding entry in neurons
as its nc
, and the previous layer's nc
as its prev
.
Upvotes: 2
Views: 165
Reputation:
You might use tag dispatching to populate the vector:
#include <iostream>
#include <vector>
template<int... neurons>
class network {
public:
std::vector<int> layers;
private:
template <int N, int... Ns>
struct tag {};
template <int N, int... Ns>
void addLayer(tag<N, Ns...>) {
layers.push_back(N);
addLayer(tag<Ns...>());
}
template <int N>
void addLayer(tag<N>) {
layers.push_back(N);
}
public:
network() {
layers.reserve(sizeof ... (neurons));
addLayer(tag<neurons...>());
}
};
int main()
{
network<1,2,3,4,5> n;
for(int i : n.layers)
std::cout << i;
std::cout << '\n';
return 0;
}
Note: Here the the count is determined by the number of integers passed to the template.
Upvotes: 0
Reputation: 302718
So first of all, you have object slicing, so you want:
std::vector<std::unique_ptr<pl>> layers;
Next, we can do this in one function without any recursion:
network() : layers() {
layers.push_back(std::make_unique<input_layer<iCount>>());
addLayers<iCount, neurons...>(std::make_index_sequence<sizeof...(neurons)>());
}
template <int... Pack, size_t... Is>
void addLayers(std::index_sequence<Is...> ) {
static constexpr int array[] = {Pack...};
int unused[] = {0,
(layers.push_back(std::make_unique<layer<array[Is+1],array[Is]>>()), 0)...
};
(void)unused;
}
This solution inspired by T.C.'s answer here.
Upvotes: 2